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

Reply via email to