[Cppunit-cvs] cppunit2/include/cpptl thread.inl, NONE, 1.1 atomiccounter.h, 1.10, 1.11 config.h, 1.
Brought to you by:
blep
From: Baptiste L. <bl...@us...> - 2006-09-06 19:23:31
|
Update of /cvsroot/cppunit/cppunit2/include/cpptl In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv3345/include/cpptl Modified Files: atomiccounter.h config.h intrusiveptr.h smallmap.h stringtools.h Added Files: thread.inl Log Message: - made atomic counter copyable - added implementation of CPPTL_ assertions. - fixed wrong assertions in smallmap.h - fixed buggy iterator usage in smallmaptest. - no longer require a library to use cpptl threads. Index: config.h =================================================================== RCS file: /cvsroot/cppunit/cppunit2/include/cpptl/config.h,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** config.h 9 Nov 2005 22:03:56 -0000 1.21 --- config.h 6 Sep 2006 19:23:26 -0000 1.22 *************** *** 208,212 **** /////////////////////////////////////////////////////////////////////////// ! # define CPPTL_ASSERT_MESSAGE( cond, message ) \ (void)(0) --- 208,212 ---- /////////////////////////////////////////////////////////////////////////// ! #ifdef NDEBUG # define CPPTL_ASSERT_MESSAGE( cond, message ) \ (void)(0) *************** *** 214,218 **** --- 214,225 ---- # define CPPTL_DEBUG_ASSERT_UNREACHABLE \ (void)(0) + #else + # include <assert.h> + # define CPPTL_ASSERT_MESSAGE( cond, message ) \ + assert( (cond) && message ) + # define CPPTL_DEBUG_ASSERT_UNREACHABLE \ + assert( false && "unreachable code" ) + #endif namespace CppTL { Index: smallmap.h =================================================================== RCS file: /cvsroot/cppunit/cppunit2/include/cpptl/smallmap.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** smallmap.h 5 Sep 2006 21:41:30 -0000 1.2 --- smallmap.h 6 Sep 2006 19:23:26 -0000 1.3 *************** *** 120,127 **** void advance( difference_type n ) { ! CPPTL_ASSERT_MESSAGE( map_ && map_->size_ && ! ( current_+n < map_->data_ + map_->size_ && current_+n >= map_->data_), ! "SmallMapIterator::advance: advancing beyond end or beginning" ); ! current_ += n; } --- 120,130 ---- void advance( difference_type n ) { ! if ( n != 0 ) ! { ! CPPTL_ASSERT_MESSAGE( map_ && map_->size_ && ! ( current_+n <= map_->data_ + map_->size_ && current_+n >= map_->data_), ! "SmallMapIterator::advance: advancing beyond end or beginning" ); ! current_ += n; ! } } --- NEW FILE: thread.inl --- #include <cpptl/thread.h> #include <vector> #if CPPTL_HAS_THREAD # ifdef CPPTL_USE_WIN32_THREAD # if !defined(APIENTRY) # undef NOMINMAX # define WIN32_LEAN_AND_MEAN # define NOGDI # define NOUSER # define NOKERNEL # define NOSOUND # define NOMINMAX # define BLENDFUNCTION void // for mingw & gcc # include <windows.h> # endif # elif defined(CPPTL_USE_PTHREAD_THREAD) # include <pthread.h> # endif // # elif defined(CPPTL_USE_PTHREAD_THREAD) #endif // Notes concerning threading implementation: // CppUnit need has very few thread-safety, hence the implementation of the threading // API need not to be highly performant. // // But, the ThreadLocalStorage should not use lock for each get/set (locking when creating // the variable in a new thread is ok though). ThreadLocalStorage is use by assertions // and this would therefore decrease the actually concurrency of the threads using assertions. namespace CppTL { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // No Thread API // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// #if !(CPPTL_HAS_THREAD) Mutex::Mutex() { } Mutex::~Mutex() { } void Mutex::lock() { } void Mutex::unlock() { } #else // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // Common Thread API implementation // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class ThreadExitHandler // ////////////////////////////////////////////////////////////////////// namespace Impl { class ThreadExitHandler : public NonCopyable { public: static ThreadExitHandler &instance() { // This static is instantiated at static construction time // so it's thread-safe static ThreadExitHandler handler; return handler; } ThreadExitHandler() : magic1_( 0x1a9cd67f ) // magic number are used to protect against , magic2_( 0x3e4a3c9d ) // possible race condition on shutdown. { } ~ThreadExitHandler() { Mutex::ScopedLockGuard guard( lock_ ); while ( !handlers_.empty() ) { handlers_.begin()->first(); handlers_.erase( handlers_.begin() ); } magic1_ = 0xdeadbeef; magic2_ = 0xdeadbeef; } void add( const Functor0 &handler, const void *tag ) { if ( !isValid() ) return; Mutex::ScopedLockGuard guard( lock_ ); Handlers::iterator it = find( tag ); if ( it == handlers_.end() ) handlers_.push_back( HandlerInfo( handler, tag ) ); else *it = HandlerInfo( handler, tag ); } void remove( const void *tag ) { if ( !isValid() ) return; Mutex::ScopedLockGuard guard( lock_ ); Handlers::iterator it = find( tag ); if ( it != handlers_.end() ) { it->first(); handlers_.erase( it ); } } void process() { if ( !isValid() ) return; Mutex::ScopedLockGuard guard( lock_ ); Handlers::iterator it = handlers_.begin(); for ( ; it != handlers_.end(); ++it ) it->first(); } private: typedef std::pair<Functor0,const void *> HandlerInfo; typedef std::vector<HandlerInfo> Handlers; Handlers::iterator find( const void *tag ) { Handlers::iterator it = handlers_.begin(); for ( ; it != handlers_.end(); ++it ) if ( it->second == tag ) return it; return handlers_.end(); } bool isValid() const { return magic1_ == 0x1a9cd67f && magic2_ == 0x3e4a3c9d; } Handlers handlers_; Mutex lock_; unsigned int magic1_; unsigned int magic2_; }; } // namespace Impl class ThreadExitHandlerInitializer { public: ThreadExitHandlerInitializer() { Impl::ThreadExitHandler::instance(); } }; // This force a call to ThreadExitHandler::instance(), // and ensure it is properly initialized. static ThreadExitHandlerInitializer threadExitInitializer; inline void addThreadExitHandler( const Functor0 &handler, const void *tag ) { Impl::ThreadExitHandler::instance().add( handler, tag ); } inline void removeThreadExitHandler( const void *tag ) { Impl::ThreadExitHandler::instance().remove( tag ); } /// This fonction must be called at the end of each thread /// to ensure ThreadLocalStorage are properly cleaned-up. inline void processThreadExitHandlers() { Impl::ThreadExitHandler::instance().process(); } # if CPPTL_USE_WIN32_THREAD // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // Thread API for WIN32 // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Mutex (win32) // ////////////////////////////////////////////////////////////////////// Mutex::Mutex() : data_( 0 ) { CRITICAL_SECTION *cs = new CRITICAL_SECTION(); ::InitializeCriticalSection( cs ); data_ = cs; } Mutex::~Mutex() { CRITICAL_SECTION *cs = static_cast<CRITICAL_SECTION *>( data_ ); if ( cs ) ::DeleteCriticalSection( cs ); delete cs; } void Mutex::lock() { CRITICAL_SECTION *cs = static_cast<CRITICAL_SECTION *>( data_ ); ::EnterCriticalSection( cs ); } void Mutex::unlock() { CRITICAL_SECTION *cs = static_cast<CRITICAL_SECTION *>( data_ ); ::LeaveCriticalSection( cs ); } // class Impl::RawThreadStorage (win32) // ////////////////////////////////////////////////////////////////////// namespace Impl { class RawThreadStorage { public: RawThreadStorage( const CppTL::Functor1<void *> &deallocator ) : deallocator_( deallocator ) { tlsIndex_ = ::TlsAlloc(); // if ( tlsIndex_ == TLS_OUT_OF_INDEXES ) // failed. // Can't throw exception => during static initialization... addThreadExitHandler( memfn0( this, &RawThreadStorage::onThreadExit ), this ); } ~RawThreadStorage() { removeThreadExitHandler( this ); ::TlsFree( tlsIndex_ ); } void onThreadExit() { deallocator_( getRawThreadStorage( this ) ); setRawThreadStorage( this, 0 ); } CppTL::Functor1<void *> deallocator_; DWORD tlsIndex_; }; RawThreadStorage *createRawThreadStorage( const CppTL::Functor1<void *> &deallocator ) { return new RawThreadStorage( deallocator ); } void freeRawThreadStorage( RawThreadStorage *storage ) { delete storage; } void *getRawThreadStorage( RawThreadStorage *storage ) { // @todo assert if NULL return ::TlsGetValue( storage->tlsIndex_ ); } void setRawThreadStorage( RawThreadStorage *storage, void *value ) { if ( ::TlsSetValue( storage->tlsIndex_, value ) == 0 ) { // @todo handle failure } } } // namespace Impl # elif defined(CPPTL_USE_PTHREAD_THREAD) // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // Thread API for PTHREAD // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Mutex (pthread) // ////////////////////////////////////////////////////////////////////// Mutex::Mutex() : data_( 0 ) { pthread_mutex_t *mutex = new pthread_mutex_t(); if ( pthread_mutex_init( mutex, 0 ) != 0 ) { // initialization error } data_ = mutex; } Mutex::~Mutex() { pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>( data_ ); if ( mutex ) pthread_mutex_destroy( mutex ); delete mutex; } void Mutex::lock() { pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>( data_ ); if ( pthread_mutex_lock( mutex ) != 0 ) { // @todo error } } void Mutex::unlock() { pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>( data_ ); if ( pthread_mutex_unlock( mutex ) != 0 ) { // @todo error } } // class Impl::ThreadLocalStorageImpl (pthread) // ////////////////////////////////////////////////////////////////////// namespace Impl { class RawThreadStorage { public: RawThreadStorage( const CppTL::Functor1<void *> &deallocator ) : deallocator_( deallocator ) { if ( pthread_key_create( &key_, 0 ) != 0 ) { // error: Can't throw exception => during static initialization } addThreadExitHandler( memfn0( this, &RawThreadStorage::onThreadExit ), this ); } ~RawThreadStorage() { removeThreadExitHandler( this ); if ( pthread_key_delete( key_ ) != 0 ) { // error: can't throw exception, during static uninitialization } } void onThreadExit() { deallocator_( getRawThreadStorage( this ) ); setRawThreadStorage( this, 0 ); } CppTL::Functor1<void *> deallocator_; pthread_key_t key_; }; RawThreadStorage *createRawThreadStorage( const CppTL::Functor1<void *> &deallocator ) { return new RawThreadStorage( deallocator ); } void freeRawThreadStorage( RawThreadStorage *storage ) { delete storage; } void *getRawThreadStorage( RawThreadStorage *storage ) { // @todo assert if NULL return pthread_getspecific( storage->key_ ); } void setRawThreadStorage( RawThreadStorage *storage, void *value ) { if ( pthread_setspecific( storage->key_, value ) != 0 ) { // @todo handle failure } } } // namespace Impl # endif // # elif defined(CPPTL_USE_PTHREAD_THREAD) #endif // #ifdef CPPTL_HAS_THREAD } // namespace CppTL Index: stringtools.h =================================================================== RCS file: /cvsroot/cppunit/cppunit2/include/cpptl/stringtools.h,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** stringtools.h 1 Feb 2006 18:26:16 -0000 1.9 --- stringtools.h 6 Sep 2006 19:23:26 -0000 1.10 *************** *** 283,305 **** // need to expose some of those utility functions... ! inline CppTL::ConstString escape( const CppTL::ConstString &text, CppTL::StringBuffer &escaped, const char *newLineEscape = "\\n" ) { ! CppTL::ConstString::const_iterator it = text.begin(); ! while ( it != text.end() ) ! escape( *it++, escaped, newLineEscape ); ! return escaped; } inline CppTL::ConstString ! quoteString( const CppTL::ConstString &text, ! const char *newLineEscape = "\\n" ) { ! CppTL::StringBuffer escaped( size_type(text.length() * 1.2) + 64 ); escaped += CppTL::ConstCharView( "\"", 1 ); ! escape(text, escaped, newLineEscape ); escaped += CppTL::ConstCharView( "\"", 1 ); return escaped; --- 283,313 ---- // need to expose some of those utility functions... ! inline void ! escapeRange( const char *first, ! const char *last, ! CppTL::StringBuffer &escaped, ! const char *newLineEscape = "\\n" ) ! { ! while ( first != last ) ! escape( *first++, escaped, newLineEscape ); ! } ! ! inline void escape( const CppTL::ConstString &text, CppTL::StringBuffer &escaped, const char *newLineEscape = "\\n" ) { ! escapeRange( text.c_str(), text.c_str() + text.length(), escaped ); } inline CppTL::ConstString ! quoteStringRange( const char *first, ! const char *last, ! const char *newLineEscape = "\\n" ) { ! CppTL::StringBuffer escaped( size_type((last-first) * 1.2) + 64 ); escaped += CppTL::ConstCharView( "\"", 1 ); ! escapeRange(first, last, escaped, newLineEscape ); escaped += CppTL::ConstCharView( "\"", 1 ); return escaped; *************** *** 308,311 **** --- 316,335 ---- inline CppTL::ConstString + quoteString( const CppTL::ConstString &text, + const char *newLineEscape = "\\n" ) + { + return quoteStringRange( text.c_str(), text.c_str() + text.length() ); + } + + + inline CppTL::ConstString + quoteMultiLineStringRange( const char *first, + const char *last ) + { + return quoteStringRange( first, last, "\\n\n" ); + } + + + inline CppTL::ConstString quoteMultiLineString( const CppTL::ConstString &str ) { Index: atomiccounter.h =================================================================== RCS file: /cvsroot/cppunit/cppunit2/include/cpptl/atomiccounter.h,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** atomiccounter.h 6 Mar 2006 22:50:53 -0000 1.10 --- atomiccounter.h 6 Sep 2006 19:23:26 -0000 1.11 *************** *** 30,34 **** # if CPPTL_USE_WIN32_ATOMIC ! class CPPTL_API AtomicCounter : public NonCopyable { public: --- 30,34 ---- # if CPPTL_USE_WIN32_ATOMIC ! class CPPTL_API AtomicCounter { public: *************** *** 70,74 **** #elif CPPTL_USE_PTHREAD_ATOMIC ! class CPPTL_API AtomicCounter : public NonCopyable { public: --- 70,74 ---- #elif CPPTL_USE_PTHREAD_ATOMIC ! class CPPTL_API AtomicCounter { public: *************** *** 79,82 **** --- 79,87 ---- } + AtomicCounter( const AtomicCounter &other ) + { + pthread_mutex_init( &lock_, 0 ); + } + ~AtomicCounter() { *************** *** 84,87 **** --- 89,97 ---- } + AtomicCounter &operator =( const AtomicCounter &other ) + { + return *this; + } + void increment() { *************** *** 126,130 **** #else ! class CPPTL_API AtomicCounter : public NonCopyable { public: --- 136,140 ---- #else ! class CPPTL_API AtomicCounter { public: Index: intrusiveptr.h =================================================================== RCS file: /cvsroot/cppunit/cppunit2/include/cpptl/intrusiveptr.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** intrusiveptr.h 11 Dec 2005 17:16:08 -0000 1.4 --- intrusiveptr.h 6 Sep 2006 19:23:26 -0000 1.5 *************** *** 116,120 **** PointeeType &operator *() const { ! // assert( p_ != 0 ) return *p_; } --- 116,120 ---- PointeeType &operator *() const { ! CPPTL_ASSERT_MESSAGE( p_ != 0, "Attempting to dereference a null pointer with operator *." ); return *p_; } *************** *** 122,125 **** --- 122,126 ---- PointeeType *operator ->() const { + CPPTL_ASSERT_MESSAGE( p_ != 0, "Attempting to use a null pointer with operator ->." ); return p_; } |