From: <ibr...@us...> - 2009-07-18 12:22:22
|
Revision: 3222 http://tora.svn.sourceforge.net/tora/?rev=3222&view=rev Author: ibre5041 Date: 2009-07-18 12:22:12 +0000 (Sat, 18 Jul 2009) Log Message: ----------- logging library Added Paths: ----------- branches/tora-trotl/src/ts_log/critical_section.h branches/tora-trotl/src/ts_log/ts_log.h branches/tora-trotl/src/ts_log/ts_log_utils.h Added: branches/tora-trotl/src/ts_log/critical_section.h =================================================================== --- branches/tora-trotl/src/ts_log/critical_section.h (rev 0) +++ branches/tora-trotl/src/ts_log/critical_section.h 2009-07-18 12:22:12 UTC (rev 3222) @@ -0,0 +1,227 @@ +#ifndef __TSLOG_CRITICAL_SECTION__ +#define __TSLOG_CRITICAL_SECTION__ +// +// thread safe logger +// +// This code is based on article by John Torjo +// published on: +// http://articles.techrepublic.com.com/5100-10878_11-5072104.html# +// + +// comment this line and uncomment the following one, +// in order to use BOOST +//#define USE_WIN32_THREAD_MANAGER +//#define USE_BOOST_THREAD_MANAGER +//#define USE_QT_THREAD_MANAGER + +//////////////////////////////////////////////////////////////////// +// thread managers + +#ifdef USE_WIN32_THREAD_MANAGER +#include <windows.h> + +// the object to be started - on a given thread +struct win32_thread_obj +{ + virtual ~win32_thread_obj() {} + virtual void operator()() = 0; +}; + + +struct win32_thread_manager +{ + typedef win32_thread_obj thread_obj_base; + + static void sleep( int nMillisecs) { Sleep( nMillisecs); } + static void create_thread( win32_thread_obj & obj) + { + DWORD dwThreadID; + CreateThread( 0, 0, + win32_thread_manager::ThreadProc, &obj, 0, &dwThreadID); + } + +// critical section for Win32 + + class critical_section + { + critical_section & operator = ( const critical_section & Not_Implemented); + critical_section( const critical_section & From); + public: + critical_section() { InitializeCriticalSection( GetCsPtr() ); } + ~critical_section() { DeleteCriticalSection( GetCsPtr() ); } + void Lock() { EnterCriticalSection( GetCsPtr()); } + void Unlock() { LeaveCriticalSection( GetCsPtr()); } + operator LPCRITICAL_SECTION() const { return GetCsPtr(); } + private: + LPCRITICAL_SECTION GetCsPtr() const { return &m_cs; } + private: + // the critical section itself + mutable CRITICAL_SECTION m_cs; + }; + + + // automatic locking/unlocking of a resource + class auto_lock_unlock + { + auto_lock_unlock operator=( auto_lock_unlock & Not_Implemented); + auto_lock_unlock( const auto_lock_unlock & Not_Implemented); + public: + auto_lock_unlock( critical_section & cs) : m_cs( cs) { m_cs.Lock(); } + ~auto_lock_unlock() { m_cs.Unlock(); } + private: + critical_section & m_cs; + }; + +private: + static DWORD WINAPI ThreadProc( LPVOID lpData) + { + win32_thread_obj * pThread = ( win32_thread_obj *)lpData; + ( *pThread)(); + return 0; + } +}; + +#endif // ifdef USE_WIN32_THREAD_MANAGER + + +#ifdef USE_BOOST_THREAD_MANAGER + +#include "boost/thread/mutex.hpp" +#include "boost/thread/thread.hpp" +#include "boost/function.hpp" +#include "boost/thread/xtime.hpp" + +class boost_thread_manager +{ +public: + struct thread_obj_base + { + virtual void operator()() = 0; + }; + +private: + struct function_wrapper + { + function_wrapper( thread_obj_base & base) : m_base( base) {} + void operator()() const { m_base(); } + private: + mutable thread_obj_base & m_base; + }; +public: + static void sleep( int nMillisecs) + { + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC); + // Sleep for n Millisecs + xt.nsec += 1000000 * nMillisecs + 100000 /* just in case*/; + boost::thread::sleep( xt); + } + + static std::string tid(void) + { + char buffer[24]; + int len = snprintf(buffer, sizeof(buffer), "%#lx", pthread_self()); + return ::std::string(buffer, len); + } + + static void create_thread( thread_obj_base & obj) + { + boost::function0< void> f = function_wrapper( obj); + // creates the thread + boost::thread t( f); + } + + + typedef boost::mutex critical_section; + typedef boost::mutex::scoped_lock auto_lock_unlock; +}; + +#endif // #ifdef USE_BOOST_THREAD_MANAGER + + +#ifdef USE_QT_THREAD_MANAGER + +#include <QMutex> +#include <QThread> + +class qt_thread_manager +{ +public: + struct thread_obj_base : public QThread + { + virtual void operator()() = 0; + private: + virtual void run() + { + (*this)(); + } + friend class qt_thread_manager; + }; + +public: + static void sleep( int nMillisecs) + { + thread_obj_base::msleep( nMillisecs); + } + + static void create_thread( thread_obj_base & obj) + { + obj.start(); + } + + static std::string tid(void) + { + char buffer[24]; + int len = snprintf(buffer, sizeof(buffer), "%#lx", pthread_self()); + return ::std::string(buffer, len); + } + + class critical_section : public QMutex + { + critical_section(const critical_section &); + public: + critical_section(void): QMutex(QMutex::NonRecursive) {}; + }; + + // automatic locking/unlocking of a resource + class auto_lock_unlock + { + auto_lock_unlock operator=( auto_lock_unlock & Not_Implemented); + auto_lock_unlock( const auto_lock_unlock & Not_Implemented); + public: + auto_lock_unlock( critical_section & cs) : m_cs( cs) { m_cs.lock(); } + ~auto_lock_unlock() { m_cs.unlock(); } + private: + critical_section & m_cs; + }; +}; + +#endif // #ifdef USE_QT_THREAD_MANAGER + + +// if you want a custom default manager, +// create your custom thread_manager class, like +// the ones shown in win32_thread_manager or +// boost_thread_manager, and +// #define DEFAULT_THREAD_MANAGER <your_custom_class> +// + +#ifdef OCI_THREAD_MANAGER +#endif // OCI_THREAD_MANAGER + +#if defined( DEFAULT_THREAD_MANAGER) +// custom thread manager +#elif defined( USE_WIN32_THREAD_MANAGER) +#define DEFAULT_THREAD_MANAGER win32_thread_manager +#elif defined( USE_BOOST_THREAD_MANAGER) +#define DEFAULT_THREAD_MANAGER boost_thread_manager +#elif defined( USE_QT_THREAD_MANAGER) +#define DEFAULT_THREAD_MANAGER qt_thread_manager +#else +#error "No thread manager. #define either of USE_WIN32_THREAD_MANAGER, USE_BOOST_THREAD_MANAGER, QT_THREAD_MANAGER" +#endif + +// END OF thread managers +//////////////////////////////////////////////////////////////////// + +#endif Added: branches/tora-trotl/src/ts_log/ts_log.h =================================================================== --- branches/tora-trotl/src/ts_log/ts_log.h (rev 0) +++ branches/tora-trotl/src/ts_log/ts_log.h 2009-07-18 12:22:12 UTC (rev 3222) @@ -0,0 +1,458 @@ +// +// thread safe logger +// +// This code is based on article by John Torjo +// published on: +// http://articles.techrepublic.com.com/5100-10878_11-5072104.html# +// + +#ifndef TS_LOG_H +#define TS_LOG_H + +#include <queue> +#include <ostream> +#include <sstream> +#include <memory> +#include <assert.h> + +/******************************************************************************** + * * + * Message string stream * + * * + ********************************************************************************/ +// forward declaration(s) +template< class char_type, class traits_type = std::char_traits< char_type> > + class basic_message_handler_log; + + +// represents the stream buffer for a message_handler_log (see below) +// Note: NOT thread-safe +template< class char_type , class traits_type = std::char_traits< char_type> > class basic_message_handler_log_streambuf + : public std::basic_streambuf< char_type, traits_type> +{ + +private: +friend class basic_message_handler_log< char_type, traits_type>; +typedef std::basic_streambuf< char_type, traits_type> streambuf_type; +typedef basic_message_handler_log< char_type, traits_type> ostream_type; +// base class +typedef std::basic_streambuf< char_type, traits_type> base_class; +//myHack +typedef typename std::basic_streambuf< char_type, traits_type>::int_type int_type; +typedef typename std::basic_streambuf< char_type, traits_type>::pos_type pos_type; +typedef typename std::basic_streambuf< char_type, traits_type>::off_type off_type; + +#ifndef __GNUC__ +using typename base_class::int_type; +using typename base_class::pos_type; +using typename base_class::off_type; +#endif + +enum { _BADOFF = -1 /* bad offset - for positioning functions */ }; + +protected: +// input, not allowed +virtual int_type pbackfail(int_type = traits_type::eof()) +{ + // only for output, not for input + assert( false); + return (traits_type::eof()); +} +virtual int showmanyc() +{ + // only for output, not for input + assert( false); + return 0; +} +virtual int_type underflow() +{ + // only for output, not for input + assert( false); + return (traits_type::eof()); +} +virtual int_type uflow() +{ + // only for output, not for input + assert( false); + return (traits_type::eof()); +} + +virtual std::streamsize xsgetn(char_type *, std::streamsize) +{ + // only for output, not for input + assert(false); + return 0; +} + +// positioning, not allowed - we're a log +virtual pos_type seekoff(off_type, std::ios_base::seekdir, + std::ios_base::openmode = std::ios_base::in | std::ios_base::out) +{ + // we don't allow positioning + assert( false); + return (std::streampos( _BADOFF)); +} +virtual pos_type seekpos(pos_type, + std::ios_base::openmode = std::ios_base::in | std::ios_base::out) +{ + // we don't allow positioning + assert( false); + return (std::streampos( _BADOFF)); +} + +// output functions +// called to write out from the internal +// buffer, into the external buffer +virtual int sync() +{ + m_pOwnerStream->on_new_message( get_stream_buffer().str() ); + m_pStreamBuffer = std::auto_ptr< string_stream_type>( new string_stream_type); + return 0; +} +virtual streambuf_type *setbuf( char_type * buffer, std::streamsize n) +{ + // ... note: this function MUST be called + // before working with this stream buffer + // we don't use a buffer - we forward everything + assert( buffer == NULL && n == 0); + this->setp( NULL, NULL); + return this; +} +// write the characters from the buffer +// to their real destination +virtual int_type overflow(int_type nChar = traits_type::eof()) +{ + if ( traits_type::not_eof( nChar)) + get_stream_buffer() << ( char_type)nChar; + return traits_type::not_eof( nChar); +} +virtual std::streamsize xsputn(const char_type *S, std::streamsize N) +{ + get_stream_buffer().write( S, N); + return N; +} + + +public: +basic_message_handler_log_streambuf() : m_pStreamBuffer( new string_stream_type) {} + +private: +typedef std::basic_ostringstream< char_type> string_stream_type; +string_stream_type & get_stream_buffer() { return *m_pStreamBuffer; } + +private: +// holds the Message, until it's flushed +std::auto_ptr< string_stream_type> m_pStreamBuffer; +// the Message Handler Log - where we write into +ostream_type * m_pOwnerStream; + +}; //template class basic_message_handler_log_streambuf + + +// derive your class from this and implement the PROTECTED on_new_message function +template< class char_type, class traits_type > + class basic_message_handler_log + : public std::basic_ostream< char_type, traits_type> +{ + typedef basic_message_handler_log_streambuf< char_type, traits_type> handler_streambuf_type; + friend class basic_message_handler_log_streambuf< char_type, traits_type>; + typedef std::basic_ostream< char_type, traits_type> base_class; + typedef std::basic_ostringstream< char_type> string_stream_type; + +protected: + typedef std::basic_string< char_type> string_type; + +basic_message_handler_log() + : base_class( NULL), m_StreamBuf() + { + m_StreamBuf.m_pOwnerStream = this; + this->init( &m_StreamBuf); + m_StreamBuf.pubsetbuf( NULL, 0); + } + +basic_message_handler_log( const basic_message_handler_log< char_type, traits_type> & from) + : base_class( NULL), m_StreamBuf() + { + m_StreamBuf.m_pOwnerStream = this; + this->init( &m_StreamBuf); + m_StreamBuf.pubsetbuf( NULL, 0); + } + + virtual ~basic_message_handler_log() {} + +protected: + virtual void on_new_message( const string_type & new_message_log) = 0; +public: + // our stream buffer + handler_streambuf_type m_StreamBuf; +}; // template class basic_message_handler_log + + +typedef basic_message_handler_log< char> message_handler_log; +typedef basic_message_handler_log< wchar_t> wmessage_handler_log; + +/******************************************************************************** + * * + * Thread safe message writers * + * * + ********************************************************************************/ + +// allows thread-safe writing +template< class char_type, class traits_type = std::char_traits< char_type> > +class thread_safe_log_writer +{ + typedef thread_safe_log_writer< char_type, traits_type> this_class; + typedef std::basic_ostream< char_type, traits_type> ostream_type; + typedef std::basic_string< char_type, traits_type> string_type; + + // forward declaration + struct thread_info; + friend struct thread_info; + + // thread-related definitions + typedef DEFAULT_THREAD_MANAGER thread_manager; + typedef typename thread_manager::thread_obj_base thread_obj_base; + typedef typename thread_manager::auto_lock_unlock auto_lock_unlock; + typedef typename thread_manager::critical_section critical_section; + + // non-copyiable + thread_safe_log_writer( const this_class &); + this_class & operator=( this_class &); + + // so that from our thread we know the object we're manipulating + struct thread_info : public thread_obj_base + { + thread_info() + : m_pThis( NULL), m_bHasFinished( false) + {} + + /* virtual */ void operator()() + { + while ( true) + { + std::string * pstr = NULL; + { + auto_lock_unlock locker( m_pThis->m_cs); + // get the string + if ( m_pThis->m_astrMessages.size() > 0) + { + pstr = m_pThis->m_astrMessages.front(); + m_pThis->m_astrMessages.pop(); + } + + // ... only when there are no more messages, + // will we ask if we should be destructed + else if ( m_pThis->m_bShouldBeDestructed) + { + // signal to the other thread we've finished + m_bHasFinished = true; + return; + } + } + + // write the string + if ( pstr) + { + m_pThis->m_underlyingLog << *pstr; + delete pstr; + } + else + // nothing to write - wait + thread_manager::sleep( 1); + } + } + + this_class * m_pThis; + volatile bool m_bHasFinished; + }; + public: + void add_message( const string_type & str) + { + auto_lock_unlock locker( m_cs); + m_astrMessages.push( new string_type( str)); + } + + thread_safe_log_writer( ostream_type & underlyingLog) + : m_bShouldBeDestructed( false), m_underlyingLog( underlyingLog) + { + m_info.m_pThis = this; + thread_manager::create_thread( m_info); + } + + ~thread_safe_log_writer() + { + // signal to the other thread we're about to be + // destructed + { + auto_lock_unlock locker( m_cs); + m_bShouldBeDestructed = true; + } + + // wait while the other thread writes all messages + while ( true) + { + auto_lock_unlock locker( m_cs); + if ( m_info.m_bHasFinished) + // the other thread has finished + break; + } + } + + critical_section & cs() const { return m_cs; } + private: + // the critical section used for thread-safe locking + mutable critical_section m_cs; + + // needed to create the other thread + thread_info m_info; + volatile bool m_bShouldBeDestructed; + + ostream_type & m_underlyingLog; + + std::queue< string_type*> m_astrMessages; +}; //class thread_safe_log_writer + + +// forward declaration +template< class char_type, class traits_type = std::char_traits< char_type> > +class basic_thread_safe_log; + + +template< class char_type, class traits_type = std::char_traits< char_type> > +class basic_internal_thread_safe_log +{ + typedef std::basic_ostream< char_type, traits_type> ostream_type; + friend class basic_thread_safe_log< char_type, traits_type>; + + // thread-related definitions + typedef DEFAULT_THREAD_MANAGER thread_manager; + typedef typename thread_manager::thread_obj_base thread_obj_base; + typedef typename thread_manager::auto_lock_unlock auto_lock_unlock; + typedef typename thread_manager::critical_section critical_section; + + // non-copyiable + typedef basic_internal_thread_safe_log< char_type, traits_type> this_class; + basic_internal_thread_safe_log( const this_class &); + this_class & operator=( this_class &); + +public: + basic_internal_thread_safe_log( ostream_type & underlyingLog) + : m_underlyingLog( underlyingLog), + m_writer( underlyingLog) + {} + + ~basic_internal_thread_safe_log() + {} + + void write_message( const std::basic_string< char_type, traits_type> & str) + { m_writer.add_message( str); } + + void copy_state_to( ostream_type & dest) const + { + auto_lock_unlock locker( m_writer.cs()); + dest.copyfmt( m_underlyingLog); + dest.setstate( m_underlyingLog.rdstate()); + } + + void copy_state_from( const ostream_type & src) + { + auto_lock_unlock locker( m_writer.cs()); + m_underlyingLog.copyfmt( src); + m_underlyingLog.setstate( m_underlyingLog.rdstate()); + } + +private: + ostream_type & m_underlyingLog; + //// !!!! reference here & m_writer + thread_safe_log_writer< char_type, traits_type> m_writer; +}; // class basic_internal_thread_safe_log + + +typedef basic_internal_thread_safe_log< char> internal_thread_safe_log; +typedef basic_internal_thread_safe_log< wchar_t> winternal_thread_safe_log; + + +template< class char_type, class traits_type> +class basic_thread_safe_log +// *** protected, not public !!! +: protected basic_message_handler_log< char_type, traits_type> +{ + typedef DEFAULT_THREAD_MANAGER thread_manager; + typedef std::basic_ostream< char_type, traits_type> ostream_type; + typedef basic_internal_thread_safe_log< char_type, traits_type> internal_type; + + typedef std::basic_string< char_type, traits_type> string_type; + +public: + basic_thread_safe_log( internal_type & tsLog) + : m_tsLog( tsLog) + { + // get underlying stream state + tsLog.copy_state_to( ts() ); + } + + basic_thread_safe_log( const basic_thread_safe_log< char_type, traits_type> & from) + // ... on some platforms, a std::ostream base copy-constructor + // might be defined as private... + : basic_message_handler_log< char_type, traits_type>(), + m_tsLog( from.m_tsLog) + { + // get underlying stream state + m_tsLog.copy_state_to( ts() ); + } + + ~basic_thread_safe_log() + { + // copy state to underlying stream + m_tsLog.copy_state_from( ts() ); + } + + // get base class - to which we can write + std::basic_ostream< char_type, traits_type> & ts() + { return *this; } + + std::basic_ostream< char_type, traits_type> & ts( const string_type /* std::string */ where) + { + static char delim[] = "--------------------------------------------------------------------------------"; + char *delimp = delim + strlen("-- "); + const std::string &tid = thread_manager::tid(); + + unsigned int color; + { + const unsigned int fnv_prime = 31; + unsigned int hash = 0; + unsigned int i = 0; + color = 30; + + for(i = 0; i < tid.length(); i++) + { + hash *= fnv_prime; + hash ^= tid.at(i); + } + hash &= 7; + color += hash; + } + /* End Of FNV Hash Function */ + + + (*this) << "\x1B" "[" << color << ";1m" << "-- " << tid << " -- " << where << " "; + delimp += strlen("-- " " -- " " ") + tid.length() + where.length(); + if(delimp < delim + sizeof(delim)) + (*this) << delimp; + (*this) << "\x1B" "[0m" << std::endl; + return (*this); + } + +protected: + virtual void on_new_message( const string_type & str) + { m_tsLog.write_message( str); } + +private: + internal_type & m_tsLog; +}; // class basic_thread_safe_log + + +typedef basic_thread_safe_log< char> thread_safe_log; +typedef basic_thread_safe_log< wchar_t> wthread_safe_log; + +#endif Added: branches/tora-trotl/src/ts_log/ts_log_utils.h =================================================================== --- branches/tora-trotl/src/ts_log/ts_log_utils.h (rev 0) +++ branches/tora-trotl/src/ts_log/ts_log_utils.h 2009-07-18 12:22:12 UTC (rev 3222) @@ -0,0 +1,51 @@ +#ifndef __TS_LOG_UTILS__ +#define __TS_LOG_UTILS__ + +#define TS_BACKTRACE_DEPTH 10 + +#include <iostream> +#include <ostream> +#include <sstream> +#ifdef __GNUC__ +#include <execinfo.h> +#include <stdlib.h> +#endif + + +namespace thread_safe_logger { + + inline std::string str_backtrace() + { + std::stringstream ret; +#ifdef __GNUC__ + void *buffer[TS_BACKTRACE_DEPTH]; + + int bsize = ::backtrace(buffer, TS_BACKTRACE_DEPTH); + char **names = backtrace_symbols (buffer, bsize); + for(int i=0; i<bsize; i++) + ret << names[i] << std::endl; + free(names); +#endif + return ret.str(); + } +}; + +#ifdef __GNUC__ + //#define __THIS_FILE__ ((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1) + //#define __HERE_SHORT__ __HERE3__(__LINE__, __FILE__) + #define __HERE_SHORT__ std::string(((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1)) + ":"__HERE1__(__LINE__) + #define __HERE__ ::thread_safe_logger::str_backtrace() + __HERE3__(__LINE__, __FILE__) + #define __HERE1__(x) STR(x)"\t" + __PRETTY_FUNCTION__ + #define __HERE2__(x,y) ::std::string("("y":" STR(x)"(") + __PRETTY_FUNCTION__ +")" + #define __HERE3__(x,y) ::std::string("\n(") + __PRETTY_FUNCTION__ + ") " y ":" STR(x) + "\n" + #define STR(a) #a +#else + #define __HERE_SHORT__ __HERE3__(__LINE__, __FILE__) + #define __HERE__ ::trotl::str_backtrace() + __HERE3__(__LINE__, __FILE__) + #define __HERE2__(x,y) ::std::string("("y":" STR(x)"(") + __FUNCTION__ +")" + #define __HERE3__(x,y) ::std::string("\n(") + __FUNCTION__ + ") " y ":" STR(x) + "\n" + #define STR(a) #a +#endif + + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2009-08-27 17:37:22
|
Revision: 3259 http://tora.svn.sourceforge.net/tora/?rev=3259&view=rev Author: ibre5041 Date: 2009-08-27 17:37:10 +0000 (Thu, 27 Aug 2009) Log Message: ----------- better way for waiting for writers thread finish Modified Paths: -------------- branches/tora-trotl/src/ts_log/critical_section.h branches/tora-trotl/src/ts_log/ts_log.h Modified: branches/tora-trotl/src/ts_log/critical_section.h =================================================================== --- branches/tora-trotl/src/ts_log/critical_section.h 2009-08-25 19:19:03 UTC (rev 3258) +++ branches/tora-trotl/src/ts_log/critical_section.h 2009-08-27 17:37:10 UTC (rev 3259) @@ -119,6 +119,18 @@ boost::thread::sleep( xt); } + static void create_thread( thread_obj_base & obj) + { + boost::function0< void> f = function_wrapper( obj); + // creates the thread + boost::thread t( f); + } + + static bool join_thread( thread_obj_base & obj) + { + TODO + } + static std::string tid(void) { //char buffer[24]; @@ -129,14 +141,6 @@ return s.str(); } - static void create_thread( thread_obj_base & obj) - { - boost::function0< void> f = function_wrapper( obj); - // creates the thread - boost::thread t( f); - } - - typedef boost::mutex critical_section; typedef boost::mutex::scoped_lock auto_lock_unlock; }; @@ -160,6 +164,10 @@ { (*this)(); } + bool join() + { + return QThread::wait(10); + } friend class qt_thread_manager; }; @@ -173,7 +181,12 @@ { obj.start(); } - + + static bool join_thread( thread_obj_base & obj) + { + return obj.join(); + } + static std::string tid(void) { //char buffer[24]; Modified: branches/tora-trotl/src/ts_log/ts_log.h =================================================================== --- branches/tora-trotl/src/ts_log/ts_log.h 2009-08-25 19:19:03 UTC (rev 3258) +++ branches/tora-trotl/src/ts_log/ts_log.h 2009-08-27 17:37:10 UTC (rev 3259) @@ -229,6 +229,7 @@ /* virtual */ void operator()() { + std::cerr << "Thread started" << std::endl; while ( true) { std::string * pstr = NULL; @@ -247,8 +248,7 @@ { // signal to the other thread we've finished m_bHasFinished = true; - // std::cerr << "Thread exit1" << std::endl; - return; + break; } } @@ -262,6 +262,8 @@ // nothing to write - wait thread_manager::sleep( 1); } + std::cerr << "Thread finished" << std::endl; + return; } this_class * m_pThis; @@ -292,16 +294,22 @@ m_bShouldBeDestructed = true; } - // wait while the other thread writes all messages - while ( true) + while(!thread_manager::join_thread( m_info)) { - //std::cerr << "~thread_safe_log_writer()2" << std::endl; - auto_lock_unlock locker( m_cs); - if ( m_info.m_bHasFinished) - // the other thread has finished - break; - thread_manager::sleep( 1); //sleep while waiting for writer thread to finish + std::cerr << "Waiting for thread:(" << m_info.m_bHasFinished << ")" << std::endl; } +/* // wait while the other thread writes all messages */ +/* while ( true) */ +/* { */ +/* { */ +/* //std::cerr << "~thread_safe_log_writer()2" << std::endl; */ +/* auto_lock_unlock locker( m_cs); */ +/* if ( m_info.m_bHasFinished) */ +/* // the other thread has finished */ +/* break; */ +/* } */ +/* thread_manager::sleep( 1); //sleep while waiting for writer thread to finish */ +/* } */ } critical_section & cs() const { return m_cs; } @@ -327,6 +335,7 @@ template< class char_type, class traits_type = std::char_traits< char_type> > class basic_internal_thread_safe_log { +protected: typedef std::basic_ostream< char_type, traits_type> ostream_type; friend class basic_thread_safe_log< char_type, traits_type>; @@ -335,7 +344,7 @@ typedef typename thread_manager::thread_obj_base thread_obj_base; typedef typename thread_manager::auto_lock_unlock auto_lock_unlock; typedef typename thread_manager::critical_section critical_section; - +private: // non-copyiable typedef basic_internal_thread_safe_log< char_type, traits_type> this_class; basic_internal_thread_safe_log( const this_class &); @@ -442,15 +451,16 @@ (*this) -#ifdef __LINUX__ +#ifdef __linux__ << "\x1B" "[" << color << ";1m" #endif << "-- " << tid << " -- " << where << " "; delimp += strlen("-- " " -- " " ") + tid.length() + where.length(); if(delimp < delim + sizeof(delim)) (*this) << delimp; + (*this) -#ifdef __LINUX__ +#ifdef __linux__ << "\x1B" "[0m" #endif << std::endl; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2010-08-31 20:06:33
|
Revision: 3676 http://tora.svn.sourceforge.net/tora/?rev=3676&view=rev Author: ibre5041 Date: 2010-08-31 20:06:27 +0000 (Tue, 31 Aug 2010) Log Message: ----------- possible fix for crash on MAC Modified Paths: -------------- branches/tora-trotl/src/ts_log/critical_section.h branches/tora-trotl/src/ts_log/thread_safe_log.h Modified: branches/tora-trotl/src/ts_log/critical_section.h =================================================================== --- branches/tora-trotl/src/ts_log/critical_section.h 2010-08-27 14:03:27 UTC (rev 3675) +++ branches/tora-trotl/src/ts_log/critical_section.h 2010-08-31 20:06:27 UTC (rev 3676) @@ -171,7 +171,12 @@ } bool join() { - return QThread::wait(10); + while(isRunning()) + { + if(!QThread::wait(50)) + QThread::yieldCurrentThread(); + } + return isFinished(); } friend class qt_thread_manager; }; Modified: branches/tora-trotl/src/ts_log/thread_safe_log.h =================================================================== --- branches/tora-trotl/src/ts_log/thread_safe_log.h 2010-08-27 14:03:27 UTC (rev 3675) +++ branches/tora-trotl/src/ts_log/thread_safe_log.h 2010-08-31 20:06:27 UTC (rev 3676) @@ -94,7 +94,7 @@ for ( int idx = 0; idx < m_pThis->m_nSumOfPriorities; ++idx) { LogWrites & writes = *( m_pThis->m_aWritesTo[ m_pThis->m_idxWrite]); - if ( writes.m_astr.size() > 0) + if (!writes.m_astr.empty()) // we found a log that we should write to break; ++m_pThis->m_idxWrite; @@ -119,7 +119,7 @@ } // we flush only when there are no more messages to write // (flushing could be time-consuming) - bDoFlush = ( writes.m_astr.size() == 0); + bDoFlush = writes.m_astr.empty(); } // ... only when there are no more messages, // will we ask if we should be destructed @@ -131,7 +131,7 @@ } } // end locked block // write the string(s) - if ( astrMsgs.size() > 0) + if ( !astrMsgs.empty()) { std::vector< std::string *>::iterator first = astrMsgs.begin(), last = astrMsgs.end(); @@ -147,10 +147,10 @@ } else // nothing to write - wait - thread_manager::sleep( 1); + thread_manager::sleep( 100); continue; unlock_and_sleep: - thread_manager::sleep( 1); + thread_manager::sleep( 100); continue; } // while(true) } // virtual operator()() @@ -350,19 +350,21 @@ { auto_lock_unlock locker( m_pThis->m_cs); // get the string - if ( m_pThis->m_astrMessages.size() > 0) + if ( !m_pThis->m_astrMessages.empty()) { pstr = m_pThis->m_astrMessages.front(); m_pThis->m_astrMessages.pop(); // we flush only when there are no more messages to write // (flushing could be time-consuming) - bDoFlush = ( m_pThis->m_astrMessages.size() == 0); + bDoFlush = m_pThis->m_astrMessages.empty(); } // ... only when there are no more messages, // will we ask if we should be destructed else if ( m_pThis->m_bShouldBeDestructed) { // signal to the other thread we've finished + m_pThis->m_underlyingLog << "Log writter thread finished." << std::endl; + m_pThis->m_underlyingLog.flush(); m_bHasFinished = true; return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2010-10-12 14:41:59
|
Revision: 3776 http://tora.svn.sourceforge.net/tora/?rev=3776&view=rev Author: ibre5041 Date: 2010-10-12 14:41:52 +0000 (Tue, 12 Oct 2010) Log Message: ----------- use colored output on console only Modified Paths: -------------- branches/tora-trotl/src/ts_log/critical_section.h branches/tora-trotl/src/ts_log/decorator.h branches/tora-trotl/src/ts_log/thread_safe_log.h branches/tora-trotl/src/ts_log/ts_log_utils.h Modified: branches/tora-trotl/src/ts_log/critical_section.h =================================================================== --- branches/tora-trotl/src/ts_log/critical_section.h 2010-10-12 14:41:08 UTC (rev 3775) +++ branches/tora-trotl/src/ts_log/critical_section.h 2010-10-12 14:41:52 UTC (rev 3776) @@ -20,7 +20,6 @@ // thread managers #ifdef USE_WIN32_THREAD_MANAGER -#define NOMINMAX #include <windows.h> // the object to be started - on a given thread @@ -28,8 +27,6 @@ { virtual ~win32_thread_obj() {} virtual void operator()() = 0; - DWORD dwThreadID; - HANDLE hHandle; }; @@ -40,22 +37,11 @@ static void sleep( int nMillisecs) { Sleep( nMillisecs); } static void create_thread( win32_thread_obj & obj) { - obj.hHandle = CreateThread( 0, 0, win32_thread_manager::ThreadProc, &obj, 0, &obj.dwThreadID); + DWORD dwThreadID; + CreateThread( 0, 0, + win32_thread_manager::ThreadProc, &obj, 0, &dwThreadID); } - static bool join_thread( thread_obj_base &obj) - { - WaitForSingleObject(obj.hHandle, INFINITE); - return true; - } - static std::string tid(void) - { - ::std::stringstream s; - s << GetCurrentThreadId(); - return s.str(); - } - - // critical section for Win32 class critical_section @@ -185,12 +171,7 @@ } bool join() { - while(isRunning()) - { - if(!QThread::wait(50)) - QThread::yieldCurrentThread(); - } - return isFinished(); + return QThread::wait(10); } friend class qt_thread_manager; }; Modified: branches/tora-trotl/src/ts_log/decorator.h =================================================================== --- branches/tora-trotl/src/ts_log/decorator.h 2010-10-12 14:41:08 UTC (rev 3775) +++ branches/tora-trotl/src/ts_log/decorator.h 2010-10-12 14:41:52 UTC (rev 3776) @@ -13,6 +13,10 @@ #include <sstream> #include <ostream> +#ifdef __linux__ +#include <stdio.h> +#endif + /******************************************************************************** * * * Small excerpt from LOKI * @@ -103,9 +107,9 @@ class decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool useColor) {}; - static inline void decorate(std::ostream &s, const std::string & here) + static inline void decorate(std::ostream &s, bool useColor, const std::string & here) {}; }; @@ -119,29 +123,29 @@ { public: enum { needs_here = IndexOf<X, hereDecorator>::value >=0 }; - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool useColor) { typedef typename X::Head Head; typedef typename X::Tail Tail; - Head::decorate(s); - Tdecorator<Tail>::decorate(s); + Head::decorate(s, useColor); + Tdecorator<Tail>::decorate(s, useColor); } - static inline void decorate(std::ostream &s, const std::string & here) + static inline void decorate(std::ostream &s, bool useColor, const std::string & here) { typedef typename X::Head Head; typedef typename X::Tail Tail; - if( IsSameType<Head, hereDecorator>::value) // do use SuperSubclass instead of IsSameType + if( IsSameType<Head, hereDecorator>::value) // TODO use SuperSubclass instead of IsSameType { - Head::decorate(s, here); + Head::decorate(s, useColor, here); } else { - Head::decorate(s); + Head::decorate(s, useColor); } if( IndexOf<Tail, hereDecorator>::value >= 0 ) { - Tdecorator<Tail>::decorate(s, here); + Tdecorator<Tail>::decorate(s, useColor, here); } else { - Tdecorator<Tail>::decorate(s); + Tdecorator<Tail>::decorate(s, useColor); } } }; @@ -150,9 +154,9 @@ class Tdecorator<NullType>: public decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool) {}; - static inline void decorate(std::ostream &s, const std::string & here) + static inline void decorate(std::ostream &s, bool, const std::string & here) {}; }; @@ -166,7 +170,7 @@ class dashDecorator : public decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool) { #ifndef min #define min(a,b) ((a < b) ? (a) : (b)) @@ -176,45 +180,51 @@ #undef min }; - static inline void decorate(std::ostream &s, const std::string & here) - {}; + static inline void decorate(std::ostream &s, bool, const std::string & here) + { + assert(0); + }; }; template<const char *c> class wordDecorator : public decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool) { s << c; }; - static inline void decorate(std::ostream &s, const std::string & here) - {}; + static inline void decorate(std::ostream &s, bool, const std::string & here) + { + assert(0); + }; }; template<const char c> class charDecorator : public decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool) { s << c; }; - static inline void decorate(std::ostream &s, const std::string & here) - {}; + static inline void decorate(std::ostream &s, bool, const std::string & here) + { + assert(0); + }; }; // The only decorator that uses second argument - __LINE__ class hereDecorator : public decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool) { - s << "Internal error: " << __HERE__; + assert(0); } - static inline void decorate(std::ostream &s, const std::string & here) + static inline void decorate(std::ostream &s, bool, const std::string & here) { s << here; } @@ -224,11 +234,14 @@ class tidDecorator : public decoratorInterface { public: - static inline void decorate(std::ostream &s) + static inline void decorate(std::ostream &s, bool useColor) { const std::string &tid = thread_manager::tid(); -#ifdef __linux__ + + unsigned int color; + + if(useColor) { const unsigned int fnv_prime = 31; unsigned int hash = 0; @@ -244,20 +257,21 @@ color += hash; } /* End Of FNV Hash Function */ -#endif - - s + #ifdef __linux__ - << "\x1B" "[" << color << ";1m" + if(useColor) + s << "\x1B" "[" << color << ";1m"; #endif - << tid + s << tid; #ifdef __linux__ - << "\x1B" "[0m" + if(useColor) + s << "\x1B" "[0m"; #endif - ; } - static inline void decorate(std::ostream &s, const std::string & here) - {}; + static inline void decorate(std::ostream &s, bool, const std::string & here) + { + assert(0); + }; }; #endif Modified: branches/tora-trotl/src/ts_log/thread_safe_log.h =================================================================== --- branches/tora-trotl/src/ts_log/thread_safe_log.h 2010-10-12 14:41:08 UTC (rev 3775) +++ branches/tora-trotl/src/ts_log/thread_safe_log.h 2010-10-12 14:41:52 UTC (rev 3776) @@ -1,5 +1,10 @@ #ifndef __THREAD_SAFE_LOG__ #define __THREAD_SAFE_LOG__ +// +// This code is based on article by John Torjo +// published on: +// http://articles.techrepublic.com.com/5100-10878_11-5072104.html# +// //// excerpt from Listing J // Solution 4 (final solution) // note: compiles with gcc 3.2, VC6 and @@ -11,6 +16,8 @@ #include <assert.h> #include <algorithm> +#include <iostream> + //////////////////////////////////////////////////////////////////// // forward declaration template< class char_type, class traits_type = std::char_traits< char_type> > @@ -30,6 +37,8 @@ virtual void write_message( const std::basic_string< char_type, traits_type> & str) = 0; virtual void copy_state_to( ostream_type & dest) const = 0; virtual void copy_state_from( const ostream_type & src) = 0; + + virtual std::basic_streambuf<char_type, traits_type>* readbuffer() const = 0; protected: basic_internal_thread_safe_log_base() {} virtual ~basic_internal_thread_safe_log_base() {}; @@ -94,7 +103,7 @@ for ( int idx = 0; idx < m_pThis->m_nSumOfPriorities; ++idx) { LogWrites & writes = *( m_pThis->m_aWritesTo[ m_pThis->m_idxWrite]); - if (!writes.m_astr.empty()) + if ( writes.m_astr.size() > 0) // we found a log that we should write to break; ++m_pThis->m_idxWrite; @@ -102,7 +111,7 @@ } // did we find a log with messages that should be written to it? LogWrites & writes = *( m_pThis->m_aWritesTo[ m_pThis->m_idxWrite]); - if ( !writes.m_astr.empty()) + if ( writes.m_astr.size() > 0) { // we get the string(s) to write to this log pLog = writes.m_pDestLog; @@ -119,7 +128,7 @@ } // we flush only when there are no more messages to write // (flushing could be time-consuming) - bDoFlush = writes.m_astr.empty(); + bDoFlush = ( writes.m_astr.size() == 0); } // ... only when there are no more messages, // will we ask if we should be destructed @@ -131,7 +140,7 @@ } } // end locked block // write the string(s) - if ( !astrMsgs.empty()) + if ( astrMsgs.size() > 0) { std::vector< std::string *>::iterator first = astrMsgs.begin(), last = astrMsgs.end(); @@ -147,10 +156,10 @@ } else // nothing to write - wait - thread_manager::sleep( 100); + thread_manager::sleep( 25); continue; unlock_and_sleep: - thread_manager::sleep( 100); + thread_manager::sleep( 25); continue; } // while(true) } // virtual operator()() @@ -301,6 +310,12 @@ m_underlyingLog.copyfmt( src); m_underlyingLog.setstate( m_underlyingLog.rdstate()); } + + std::basic_streambuf<char_type, traits_type>* readbuffer() const + { + return m_underlyingLog.rdbuf(); + } + private: ostream_type & m_underlyingLog; // IMPORTANT: keep it by reference! @@ -350,21 +365,19 @@ { auto_lock_unlock locker( m_pThis->m_cs); // get the string - if ( !m_pThis->m_astrMessages.empty()) + if ( m_pThis->m_astrMessages.size() > 0) { pstr = m_pThis->m_astrMessages.front(); m_pThis->m_astrMessages.pop(); // we flush only when there are no more messages to write // (flushing could be time-consuming) - bDoFlush = m_pThis->m_astrMessages.empty(); + bDoFlush = ( m_pThis->m_astrMessages.size() == 0); } // ... only when there are no more messages, // will we ask if we should be destructed else if ( m_pThis->m_bShouldBeDestructed) { // signal to the other thread we've finished - m_pThis->m_underlyingLog << "Log writter thread finished." << std::endl; - m_pThis->m_underlyingLog.flush(); m_bHasFinished = true; return; } @@ -379,7 +392,7 @@ } else // nothing to write - wait - thread_manager::sleep( 100); + thread_manager::sleep( 25); } } this_class * m_pThis; @@ -461,6 +474,11 @@ m_underlyingLog.copyfmt( src); m_underlyingLog.setstate( m_underlyingLog.rdstate()); } + + std::basic_streambuf<char_type, traits_type>* readbuffer() const + { + return m_underlyingLog.rdbuf(); + } private: ostream_type & m_underlyingLog; log_writer_ownthread m_writer; @@ -479,12 +497,12 @@ template< class char_type, class traits_type> class invalid_streambuf : public std::basic_streambuf< char_type, traits_type> { - #ifndef __GNUC__ +#ifndef __GNUC__ typedef std::basic_streambuf< char_type, traits_type> base_class; using typename base_class::int_type; - #else +#else typedef typename std::basic_streambuf< char_type, traits_type>::int_type int_type; - #endif +#endif protected: void bad_call() { @@ -537,11 +555,12 @@ { // get underlying stream state tsLog.copy_state_to( ts() ); + useColor = is_color_terminal(tsLog); } basic_thread_safe_log( const basic_thread_safe_log< char_type, traits_type> & from) // ... on some platforms, a std::ostream base copy-constructor // might be defined as private... - : basic_message_handler_log< char_type, traits_type>(), m_tsLog( from.m_tsLog) + : basic_message_handler_log< char_type, traits_type>(), m_tsLog( from.m_tsLog), useColor(from.useColor) { // get underlying stream state m_tsLog.copy_state_to( ts() ); @@ -553,9 +572,10 @@ this->write_last_message( *this); #ifndef NDEBUG // debug-mode - this->rdbuf( &(invalid_streambuf< char_type, traits_type>::s_instance)); + std::basic_ios<char_type, traits_type>::rdbuf( &(invalid_streambuf< char_type, traits_type>::s_instance)); #endif } + // get base class - to which we can write std::basic_ostream< char_type, traits_type> & ts() { return *this; } @@ -564,12 +584,11 @@ std::basic_ostream< char_type, traits_type> & ts( const string_type & /* std::string */ where) { if( decorator::needs_here) - decorator::decorate( *this, where); + decorator::decorate( *this, useColor, where); else - decorator::decorate( *this); - //std::stringstream s; // TODO - //s << where; - // TODO decorator here + decorator::decorate( *this, useColor); + //std::stringstream s; + //s << decorator::decorate( *this, useColor, where); //return ( *this) << s.str(); return ( *this); } @@ -587,7 +606,16 @@ m_tsLog.write_message( str); } private: - internal_type & m_tsLog; + static bool is_color_terminal(internal_type const &t) + { + if( isatty(1) && isatty(2) && t.readbuffer() == std::cout.rdbuf()) + return true; + else + return false; + } + + internal_type &m_tsLog; + bool useColor; }; // template class basic_thread_safe_log typedef basic_thread_safe_log< char> thread_safe_log; typedef basic_thread_safe_log< wchar_t> wthread_safe_log; Modified: branches/tora-trotl/src/ts_log/ts_log_utils.h =================================================================== --- branches/tora-trotl/src/ts_log/ts_log_utils.h 2010-10-12 14:41:08 UTC (rev 3775) +++ branches/tora-trotl/src/ts_log/ts_log_utils.h 2010-10-12 14:41:52 UTC (rev 3776) @@ -2,9 +2,6 @@ #define __TS_LOG_UTILS__ #ifndef __HERE__ - -#ifdef DEBUG - #ifdef __GNUC__ #define __HERE__ std::string(((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1)) + ":"__HERE1__(__LINE__) #define __HERE1__(x) STR(x)"\t" + __PRETTY_FUNCTION__ @@ -14,12 +11,7 @@ #define __HERE1__(x) STR(x)"\t" + __FUNCSIG__ #define STR(a) #a #endif - -#else -#define __HERE__ "" #endif -#endif - #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ibr...@us...> - 2010-11-10 16:32:16
|
Revision: 3807 http://tora.svn.sourceforge.net/tora/?rev=3807&view=rev Author: ibre5041 Date: 2010-11-10 16:32:10 +0000 (Wed, 10 Nov 2010) Log Message: ----------- use isatty on windows Modified Paths: -------------- branches/tora-trotl/src/ts_log/decorator.h branches/tora-trotl/src/ts_log/thread_safe_log.h Modified: branches/tora-trotl/src/ts_log/decorator.h =================================================================== --- branches/tora-trotl/src/ts_log/decorator.h 2010-11-10 12:31:00 UTC (rev 3806) +++ branches/tora-trotl/src/ts_log/decorator.h 2010-11-10 16:32:10 UTC (rev 3807) @@ -13,6 +13,8 @@ #include <sstream> #include <ostream> +#include <assert.h> + #ifdef __linux__ #include <stdio.h> #endif Modified: branches/tora-trotl/src/ts_log/thread_safe_log.h =================================================================== --- branches/tora-trotl/src/ts_log/thread_safe_log.h 2010-11-10 12:31:00 UTC (rev 3806) +++ branches/tora-trotl/src/ts_log/thread_safe_log.h 2010-11-10 16:32:10 UTC (rev 3807) @@ -18,6 +18,10 @@ #include <iostream> +#ifdef WIN32 +#include <io.h> +#endif + //////////////////////////////////////////////////////////////////// // forward declaration template< class char_type, class traits_type = std::char_traits< char_type> > @@ -608,7 +612,11 @@ private: static bool is_color_terminal(internal_type const &t) { +#ifdef WIN32 + if( _isatty(1) && _isatty(2) && t.readbuffer() == std::cout.rdbuf()) +#else if( isatty(1) && isatty(2) && t.readbuffer() == std::cout.rdbuf()) +#endif return true; else return false; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |