Sound pretty good, I'll have a deeper look in a few days.
I thought about that too, but went in a more pedantic C way,
On Thursday 17 December 2009 12:53, Gabriel M. Beddingfield wrote :
>
>
> On Tue, 15 Dec 2009, Gabriel M. Beddingfield wrote:
>
> > However, a string class could be created that meets the requirement:
> >
> > template <typename CharT, size_t Max>
> > class RtString
> > {
> [snip]
>
> OK, for some reason I've been obsessed with this class for
> the past few days. You can find my work here:
>
> http://gitorious.org/composite/composite-labs/trees/master/200912-rtstring
>
> Especially the RtString.hpp header file. This class has
> been tested and is pretty stable now.[1]
>
> Not only is it real-time safe, but copying its contents to a
> char* buffer is real-time safe. On top of that, it's
> friggin' fast. I've benchmarked it as follows:
>
> RtString is 3x faster than std::ostream + std::string
> RtString is 5-6x faster than QString
> RtString is 5-6x faster than boost::format + std::string
>
> Comments are welcome!
>
> Peace,
> Gabriel
>
> [1] at least with CharT = char.
>
> ------------------------------------------------------------------------------
> This SF.Net email is sponsored by the Verizon Developer Community
> Take advantage of Verizon's best-in-class app development support
> A streamlined, 14 day to market process makes app distribution fast and easy
> Join now and get one step closer to millions of Verizon customers
> http://p.sf.net/sfu/verizon-dev2dev
> _______________________________________________
> Hydrogen-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/hydrogen-devel
>
> !DSPAM:4b2a7ed423918658827628!
>
--
Jérémy Zurcher
rte de Cully 29
1091 Grandvaux
+41 (0) 79 599 84 27
#include <map>
#include <cassert>
#include <iostream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <pthread.h>
using namespace std;
class Object;
/****************************************************************************************************************/
pthread_t loggerThread;
void* loggerThread_func(void* param);
/****************************************************************************************************************/
class Logger {
public:
~Logger();
Logger( unsigned nmemb, unsigned mlen );
inline unsigned read_idx() { return __read_idx; }
inline unsigned write_idx() { return __write_idx; }
inline void inc_read_idx() { __read_idx = (__read_idx+1)%__nmemb; }
inline void inc_write_idx() { __write_idx = (__write_idx+1)%__nmemb; }
inline bool is_empty() { return __read_idx==__write_idx; }
inline char* read_buffer() { return __rr_buffer[__read_idx]; }
inline char* write_buffer() { return __rr_buffer[__write_idx]; }
// could use stdarg
int log( const char* cls, const char* msg, const char* arg1, const char* arg2, const char* arg3 );
friend void* loggerThread_func(void* param);
private:
bool __running;
unsigned __nmemb;
unsigned __mlen;
unsigned __read_idx;
unsigned __write_idx;
char** __rr_buffer;
pthread_mutex_t __mutex;
};
/****************************************************************************************************************/
class Object {
public:
typedef map<const char*, int> object_count_t;
Object( const char* class_name ) { add_object( this, class_name ); }
Object( const Object& obj ) { add_object( this, obj.class_name() ); }
~Object() {
#ifdef DEBUG
cerr<<"~Object()"<<endl;
#endif
}
virtual const char* class_name() const = 0;
virtual void Destroy() = 0;
static void write_objects_map(ostream &out ) {
int n = 0;
ostringstream o;
pthread_mutex_lock( &__mutex );
object_count_t::iterator it = __objects_count.begin();
while ( it != __objects_count.end() ) {
o << "\t[ " << (*it).first << " ]\t" << (*it).second << endl;
n+=(*it).second;
it++;
}
pthread_mutex_unlock( &__mutex );
out << endl << "Objects map : " << endl << o.str() << "Total : " << n << " objects." << endl << endl;
return;
}
static void write_objects_map_to_cerr() { Object::write_objects_map( cerr ); }
static void install_logger( Logger *logger ) {
__logger = logger;
pthread_mutex_init( &__mutex, NULL ); // TODO should go somewhere else ??
}
/* must be called before the object is really deleted */
static inline void del_object( Object* obj ) {
object_count_t::iterator it = __objects_count.find( obj->class_name() );
if ( it==__objects_count.end() ) {
cerr << "delete an unreferenced object !!!" << endl;
return;
}
pthread_mutex_lock( &__mutex );
assert(__objects_count[ (*it).first ]>0);
__objects_count[ (*it).first ]--;
pthread_mutex_unlock( &__mutex );
}
private:
static inline void add_object( Object* obj, const char* class_name ) {
pthread_mutex_lock( &__mutex );
if( __objects_count.size()==0) atexit( Object::write_objects_map_to_cerr );
__objects_count[ class_name ]++;
pthread_mutex_unlock( &__mutex );
#ifdef DEBUG
fprintf(stderr,"new object : %X\n",obj);
#endif
}
static Logger* __logger;
static object_count_t __objects_count;
static pthread_mutex_t __mutex;
protected:
static inline int log( Object* obj, const char* msg, const char* arg1=NULL, const char* arg2=NULL, const char* arg3=NULL) {
assert( __logger!=0 );
return __logger->log( obj->class_name(), msg, arg1, arg2, arg3 );
}
};
/* Object class instance */
pthread_mutex_t Object::__mutex;
Logger* Object::__logger = 0;
Object::object_count_t Object::__objects_count;
/****************************************************************************************************************/
Logger::Logger( unsigned nmemb, unsigned mlen ) : __running(true) {
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_mutex_init( &__mutex, NULL );
pthread_create( &loggerThread, &attr, loggerThread_func, this );
__mlen = mlen;
__nmemb = nmemb;
__rr_buffer = (char**)malloc( __nmemb * sizeof( char*) );
if(__rr_buffer==NULL) { /* TODO */ }
for(int i=0;i<__mlen;i++) {
__rr_buffer[i] = (char*)malloc( __mlen * sizeof(char) );
if(__rr_buffer[i]==NULL) { /* TODO */ }
}
__write_idx = __read_idx = 0;
}
Logger::~Logger() {
__running = false;
pthread_join( loggerThread, NULL );
for(int i=0;i<__mlen;i++) free( __rr_buffer[i] );
free(__rr_buffer);
}
int Logger::log( const char* cls, const char* msg, const char* arg1, const char* arg2, const char* arg3 ) {
int ret=0;
pthread_mutex_lock( &__mutex );
char *buffer = write_buffer();
ret += snprintf( buffer, __mlen, "[ %s ] ", cls );
if(ret<__mlen) {
ret += snprintf( buffer+ret, __mlen-ret, msg, arg1, arg2, arg3);
}
buffer[__mlen-2]='\n';
buffer[__mlen-1]='\0';
inc_write_idx();
if(__write_idx==__read_idx) inc_read_idx();
pthread_mutex_unlock( &__mutex );
return ret;
}
/****************************************************************************************************************/
void* loggerThread_func(void* param) {
if ( param == NULL ) {
cerr << "Logger instance missing" << endl;
return NULL;
}
Logger *logger = ( Logger* )param;
while ( logger->__running ) {
usleep( 1000 );
while(!logger->is_empty()) {
cerr << logger->read_buffer();
pthread_mutex_lock( &logger->__mutex );
logger->inc_read_idx();
pthread_mutex_unlock( &logger->__mutex );
}
}
}
/****************************************************************************************************************/
#define _OBJECT( __cls__ ) \
public: virtual const char* class_name() const { return __class_name; } \
private: static const char* __class_name; \
public: ~__cls__() { Object::del_object(this); Destroy(); } \
/****************************************************************************************************************/
class Dev1 : public Object {
_OBJECT( Dev1 )
public:
Dev1() :Object(__class_name) {
#ifdef DEBUG
cerr<<"Dev1::Dev1()"<<endl;
#endif
log( this, msg_create );
}
void Destroy() {
#ifdef DEBUG
cerr<<"Dev1::Destroy()"<<endl;
#endif
log( this, msg_destroy );
}
void say_hello( char* name ) {
log( this, msg_hello, name, "Zurcher" );
}
static const char *msg_create;
static const char *msg_destroy;
static const char *msg_hello;
};
const char* Dev1::__class_name="Dev1";
const char* Dev1::msg_create = "Object Creation\n";
const char* Dev1::msg_destroy = "Object Destruction\n";
const char* Dev1::msg_hello = ">>>Hello %s %s<<<\n";
/****************************************************************************************************************/
class Dev2 : public Object {
_OBJECT( Dev2 )
public:
Dev2() :Object(__class_name){ }
void Destroy() { }
};
const char* Dev2::__class_name="Dev2";
/****************************************************************************************************************/
int run() {
Dev1 a = Dev1(); Dev1 b = Dev1(); Dev2 c = Dev2(); Dev2 d = Dev2(); Dev2 e = Dev2( d );
a.say_hello( (char*)"Jeremy" );
Object* o = &a;
a.say_hello( (char*)"Corina" );
Object::write_objects_map( cerr );
a.say_hello( (char*)"Roisin" );
}
int main () {
Logger *l = new Logger(5,35);
Object::install_logger( l );
run();
usleep(1000);
}
------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________
Hydrogen-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/hydrogen-devel