You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(80) |
Aug
(36) |
Sep
(120) |
Oct
(89) |
Nov
(57) |
Dec
(22) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(308) |
Feb
(66) |
Mar
(88) |
Apr
(54) |
May
(43) |
Jun
(40) |
Jul
(33) |
Aug
(1) |
Sep
(7) |
Oct
(65) |
Nov
(19) |
Dec
(10) |
2007 |
Jan
(5) |
Feb
(8) |
Mar
(7) |
Apr
|
May
(7) |
Jun
|
Jul
(5) |
Aug
(3) |
Sep
(1) |
Oct
|
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
(5) |
Apr
|
May
(5) |
Jun
(21) |
Jul
(27) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
(5) |
Dec
(10) |
2009 |
Jan
(67) |
Feb
(3) |
Mar
(26) |
Apr
(2) |
May
|
Jun
(1) |
Jul
|
Aug
(2) |
Sep
(10) |
Oct
(18) |
Nov
(20) |
Dec
(3) |
2010 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(9) |
Oct
(3) |
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(7) |
Jul
|
Aug
|
Sep
(39) |
Oct
(43) |
Nov
(7) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(7) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <ric...@us...> - 2011-09-06 23:56:35
|
Revision: 1091 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1091&view=rev Author: rich_sposato Date: 2011-09-06 23:56:29 +0000 (Tue, 06 Sep 2011) Log Message: ----------- Changed return statements and define section to fix bug 3106378. Modified Paths: -------------- trunk/include/loki/SafeBits.h Modified: trunk/include/loki/SafeBits.h =================================================================== --- trunk/include/loki/SafeBits.h 2011-09-06 23:21:38 UTC (rev 1090) +++ trunk/include/loki/SafeBits.h 2011-09-06 23:56:29 UTC (rev 1091) @@ -333,17 +333,17 @@ SafeBitField operator & ( const SafeBitField & rhs ) const { return SafeBitField( word & rhs.word ); } SafeBitField operator ^ ( const SafeBitField & rhs ) const { return SafeBitField( word ^ rhs.word ); } SafeBitField operator ~ ( void ) const { return SafeBitField( ~word ); } - SafeBitField operator |= ( const SafeBitField & rhs ) { word |= rhs.word; return SafeBitField( *this ); } - SafeBitField operator &= ( const SafeBitField & rhs ) { word &= rhs.word; return SafeBitField( *this ); } - SafeBitField operator ^= ( const SafeBitField & rhs ) { word ^= rhs.word; return SafeBitField( *this ); } + SafeBitField operator |= ( const SafeBitField & rhs ) { word |= rhs.word; return *this; } + SafeBitField operator &= ( const SafeBitField & rhs ) { word &= rhs.word; return *this; } + SafeBitField operator ^= ( const SafeBitField & rhs ) { word ^= rhs.word; return *this; } /// Bitwise operators that use bit-constants. SafeBitField operator | ( const_t rhs ) const { return SafeBitField( word | rhs.word ); } SafeBitField operator & ( const_t rhs ) const { return SafeBitField( word & rhs.word ); } SafeBitField operator ^ ( const_t rhs ) const { return SafeBitField( word ^ rhs.word ); } - SafeBitField operator |= ( const_t rhs ) { word |= rhs.word; return SafeBitField( *this ); } - SafeBitField operator &= ( const_t rhs ) { word &= rhs.word; return SafeBitField( *this ); } - SafeBitField operator ^= ( const_t rhs ) { word ^= rhs.word; return SafeBitField( *this ); } + SafeBitField operator |= ( const_t rhs ) { word |= rhs.word; return *this; } + SafeBitField operator &= ( const_t rhs ) { word &= rhs.word; return *this; } + SafeBitField operator ^= ( const_t rhs ) { word ^= rhs.word; return *this; } // Conversion to bool. // This is a major source of headaches, but it's required to support code like this: @@ -471,7 +471,11 @@ // This creates a typedef field_t for SafeBitField<unique_index, ulong> where index is the current line number. Since line numbers __LINE__ are counted // separately for all header files, this ends up being the same type in all files using the header which defines field_t. #ifdef LOKI_SAFE_BIT_FIELD - #define LOKI_BIT_FIELD( word_t ) typedef SafeBitField<__LINE__, word_t> + #ifdef __COUNTER__ + #define LOKI_BIT_FIELD( word_t ) typedef ::Loki::SafeBitField<__COUNTER__, word_t> + #else + #define LOKI_BIT_FIELD( word_t ) typedef ::Loki::SafeBitField<__LINE__, word_t> + #endif #else #define LOKI_BIT_FIELD( word_t ) typedef word_t #endif // LOKI_SAFE_BIT_FIELD This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-09-06 23:21:44
|
Revision: 1090 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1090&view=rev Author: rich_sposato Date: 2011-09-06 23:21:38 +0000 (Tue, 06 Sep 2011) Log Message: ----------- Added return type and return statements to fix bug 3399654. Modified Paths: -------------- trunk/include/loki/Threads.h Modified: trunk/include/loki/Threads.h =================================================================== --- trunk/include/loki/Threads.h 2011-09-06 23:01:26 UTC (rev 1089) +++ trunk/include/loki/Threads.h 2011-09-06 23:21:38 UTC (rev 1090) @@ -127,11 +127,17 @@ return lval; \ } \ \ - static void AtomicAssign(volatile IntType& lval, const IntType val) \ - { InterlockedExchange(&const_cast<IntType&>(lval), val); } \ + static IntType AtomicAssign(volatile IntType& lval, const IntType val) \ + { \ + InterlockedExchange(&const_cast<IntType&>(lval), val); \ + return lval; \ + } \ \ - static void AtomicAssign(IntType& lval, volatile const IntType& val) \ - { InterlockedExchange(&lval, val); } \ + static IntType AtomicAssign(IntType& lval, volatile const IntType& val) \ + { \ + InterlockedExchange(&lval, val); \ + return lval; \ + } \ \ static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches ) \ { \ @@ -249,7 +255,7 @@ return lval; \ } \ \ - static void AtomicAssign(volatile IntType& lval, const IntType val) \ + static IntType AtomicAssign(volatile IntType& lval, const IntType val) \ { \ ::pthread_mutex_lock( &atomic_mutex_ ); \ lval = val; \ @@ -257,7 +263,7 @@ return lval; \ } \ \ - static void AtomicAssign(IntType& lval, volatile const IntType& val) \ + static IntType AtomicAssign(IntType& lval, volatile const IntType& val) \ { \ ::pthread_mutex_lock( &atomic_mutex_ ); \ lval = val; \ @@ -394,11 +400,17 @@ static IntType AtomicDecrement(volatile IntType& lval) { return --lval; } - static void AtomicAssign(volatile IntType & lval, const IntType val) - { lval = val; } + static IntType AtomicAssign(volatile IntType & lval, const IntType val) + { + lval = val; + return lval; + } - static void AtomicAssign(IntType & lval, volatile IntType & val) - { lval = val; } + static IntType AtomicAssign(IntType & lval, volatile IntType & val) + { + lval = val; + return lval; + } static IntType AtomicAdd(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-09-06 23:01:32
|
Revision: 1089 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1089&view=rev Author: rich_sposato Date: 2011-09-06 23:01:26 +0000 (Tue, 06 Sep 2011) Log Message: ----------- Added include statement to fix bug 3399706. Modified Paths: -------------- trunk/include/loki/LevelMutex.h Modified: trunk/include/loki/LevelMutex.h =================================================================== --- trunk/include/loki/LevelMutex.h 2011-06-21 08:08:18 UTC (rev 1088) +++ trunk/include/loki/LevelMutex.h 2011-09-06 23:01:26 UTC (rev 1089) @@ -30,6 +30,7 @@ #include <pthread.h> #endif +#include <exception> #include <vector> #include <assert.h> #include <time.h> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 08:08:24
|
Revision: 1088 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1088&view=rev Author: rich_sposato Date: 2011-06-21 08:08:18 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Moved location of #include statements inside file. Modified Paths: -------------- trunk/include/loki/LevelMutex.h Modified: trunk/include/loki/LevelMutex.h =================================================================== --- trunk/include/loki/LevelMutex.h 2011-06-21 03:35:30 UTC (rev 1087) +++ trunk/include/loki/LevelMutex.h 2011-06-21 08:08:18 UTC (rev 1088) @@ -24,17 +24,17 @@ // ---------------------------------------------------------------------------- -#include <vector> -#include <assert.h> -#include <time.h> - #if defined( _MSC_VER ) #include <Windows.h> #else #include <pthread.h> #endif -#if !defined(_WIN32) && !defined(_WIN64) +#include <vector> +#include <assert.h> +#include <time.h> + +#if !defined( _WIN32 ) && !defined( _WIN64 ) #include <unistd.h> // declares usleep under Linux #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 03:35:36
|
Revision: 1087 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1087&view=rev Author: rich_sposato Date: 2011-06-21 03:35:30 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Changed preprocessor statements to provide clarity. Modified Paths: -------------- trunk/include/loki/ThreadLocal.h Modified: trunk/include/loki/ThreadLocal.h =================================================================== --- trunk/include/loki/ThreadLocal.h 2011-06-21 03:32:19 UTC (rev 1086) +++ trunk/include/loki/ThreadLocal.h 2011-06-21 03:35:30 UTC (rev 1087) @@ -20,19 +20,28 @@ // First assume the compiler does allow thread-local storage by #defining the // macro which allows compiler to see the code inside this file. -// Then #undef the macro for compilers which are known for not supporting -// thread-local storage. +// Then #undef the macro for compilers which do not support thread-local +// storage or do not implement it correctly. #define LOKI_THINKS_COMPILER_ALLOWS_THREAD_LOCAL_STORAGE 1 -// The __APPLE__ macro does not refer to a compiler, but to the Apple OSX operating system. -#if defined( __APPLE__ ) - #warning "GCC for Apple does not allow thread_local storage, so you can not use some parts of Loki." - #undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE -#endif +#if defined( __GNUC__ ) + // The __APPLE__ macro does not refer to a compiler, but to the Apple OSX operating system. + #if defined( __APPLE__ ) + #warning "GCC for Apple does not allow thread_local storage, so you can not use some parts of Loki." + #undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE -#if ( defined( __CYGWIN__ ) && ( __GNUC__ <= 3 ) ) - #warning "Older versions of GCC for Cygwin do not allow thread_local storage, so you can not use some parts of Loki." - #undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE + #elif defined( __CYGWIN__ ) + #if ( __GNUC__ <= 3 ) + #warning "Older versions of GCC for Cygwin do not allow thread_local storage, so you can not use some parts of Loki." + #undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE + #endif + + #elif ( __GNUC__ == 4 ) // GNU versions other than Cygwin. + #if ( __GNUC_MINOR__ == 4 ) + #warning "GCC version 4.4 implements thread_local storage incorrectly, so you can not use some parts of Loki." + #undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE + #endif + #endif #endif #if defined( LOKI_THINKS_COMPILER_ALLOWS_THREAD_LOCAL_STORAGE ) && !defined( LOKI_THREAD_LOCAL ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 03:32:25
|
Revision: 1086 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1086&view=rev Author: rich_sposato Date: 2011-06-21 03:32:19 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Minor changes to preprocessor statements. Modified Paths: -------------- trunk/include/loki/Threads.h Modified: trunk/include/loki/Threads.h =================================================================== --- trunk/include/loki/Threads.h 2011-06-21 03:29:50 UTC (rev 1085) +++ trunk/include/loki/Threads.h 2011-06-21 03:32:19 UTC (rev 1086) @@ -52,7 +52,7 @@ #include <cassert> -#if defined(LOKI_CLASS_LEVEL_THREADING) || defined(LOKI_OBJECT_LEVEL_THREADING) +#if defined( LOKI_CLASS_LEVEL_THREADING ) || defined( LOKI_OBJECT_LEVEL_THREADING ) #define LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL ::Loki::ClassLevelLockable @@ -77,11 +77,11 @@ #endif -#ifndef LOKI_DEFAULT_MUTEX -#define LOKI_DEFAULT_MUTEX ::Loki::Mutex +#if !defined( LOKI_DEFAULT_MUTEX ) + #define LOKI_DEFAULT_MUTEX ::Loki::Mutex #endif -#ifdef LOKI_WINDOWS_H +#if defined( LOKI_WINDOWS_H ) #define LOKI_THREADS_MUTEX(x) CRITICAL_SECTION (x); #define LOKI_THREADS_MUTEX_INIT(x) ::InitializeCriticalSection (x) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 03:29:56
|
Revision: 1085 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1085&view=rev Author: rich_sposato Date: 2011-06-21 03:29:50 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Removed trailing whitespaces. Modified Paths: -------------- trunk/include/loki/Singleton.h Modified: trunk/include/loki/Singleton.h =================================================================== --- trunk/include/loki/Singleton.h 2011-06-21 01:16:29 UTC (rev 1084) +++ trunk/include/loki/Singleton.h 2011-06-21 03:29:50 UTC (rev 1085) @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_SINGLETON_INC_ @@ -30,9 +30,9 @@ #include <memory> #ifdef _MSC_VER -#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl +#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl #else -#define LOKI_C_CALLING_CONVENTION_QUALIFIER +#define LOKI_C_CALLING_CONVENTION_QUALIFIER #endif /// \defgroup SingletonGroup Singleton @@ -42,7 +42,7 @@ /// \ingroup SingletonGroup /// The lifetimes of the singleton. /// \par Special lifetime for SmallObjects -/// When the holded object is a Small(Value)Object or the holded object +/// When the holded object is a Small(Value)Object or the holded object /// uses objects which are or inherit from Small(Value)Object /// then you can't use the default lifetime: you must use the lifetime /// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode @@ -58,14 +58,14 @@ { #ifndef LOKI_MAKE_DLL - void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below + void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below #else void LOKI_EXPORT AtExitFn(); #endif class LifetimeTracker; -#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL +#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL #ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL // Helper data @@ -87,23 +87,23 @@ class LifetimeTracker { public: - LifetimeTracker(unsigned int x) : longevity_(x) + LifetimeTracker(unsigned int x) : longevity_(x) {} - + virtual ~LifetimeTracker() = 0; - + static bool Compare(const LifetimeTracker* lhs, const LifetimeTracker* rhs) { return lhs->longevity_ > rhs->longevity_; } - + private: unsigned int longevity_; }; - + // Definition required - inline LifetimeTracker::~LifetimeTracker() {} + inline LifetimeTracker::~LifetimeTracker() {} // Helper destroyer function template <typename T> @@ -124,11 +124,13 @@ , pTracked_(p) , destroyer_(d) {} - + ~ConcreteLifetimeTracker() { destroyer_(pTracked_); } - + private: + /// Copy constructor is not implemented. + ConcreteLifetimeTracker( const ConcreteLifetimeTracker & ); T* pTracked_; Destroyer destroyer_; }; @@ -137,8 +139,8 @@ //////////////////////////////////////////////////////////////////////////////// /// \ingroup LifetimeGroup - /// - /// Assigns an object a longevity; ensures ordered destructions of objects + /// + /// Assigns an object a longevity; ensures ordered destructions of objects /// registered thusly during the exit sequence of the application //////////////////////////////////////////////////////////////////////////////// @@ -155,58 +157,58 @@ pTrackerArray = new TrackerArray; // automatically delete the ConcreteLifetimeTracker object when a exception is thrown - std::auto_ptr<LifetimeTracker> + std::auto_ptr<LifetimeTracker> p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) ); // Find correct position TrackerArray::iterator pos = std::upper_bound( - pTrackerArray->begin(), - pTrackerArray->end(), - p.get(), + pTrackerArray->begin(), + pTrackerArray->end(), + p.get(), LifetimeTracker::Compare); - + // Insert the pointer to the ConcreteLifetimeTracker object into the queue pTrackerArray->insert(pos, p.get()); - + // nothing has thrown: don't delete the ConcreteLifetimeTracker object p.release(); - + // Register a call to AtExitFn std::atexit(Private::AtExitFn); } #else - + template <typename T, typename Destroyer> void SetLongevity(T* pDynObject, unsigned int longevity, Destroyer d) { using namespace Private; - + TrackerArray pNewArray = static_cast<TrackerArray>( - std::realloc(pTrackerArray, + std::realloc(pTrackerArray, sizeof(*pTrackerArray) * (elements + 1))); if (!pNewArray) throw std::bad_alloc(); - + // Delayed assignment for exception safety pTrackerArray = pNewArray; - + LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>( pDynObject, longevity, d); - + // Insert a pointer to the object into the queue TrackerArray pos = std::upper_bound( - pTrackerArray, - pTrackerArray + elements, - p, + pTrackerArray, + pTrackerArray + elements, + p, LifetimeTracker::Compare); std::copy_backward( - pos, + pos, pTrackerArray + elements, pTrackerArray + elements + 1); *pos = p; ++elements; - + // Register a call to AtExitFn std::atexit(Private::AtExitFn); } @@ -221,21 +223,21 @@ } //////////////////////////////////////////////////////////////////////////////// - /// \struct CreateUsingNew + /// \struct CreateUsingNew /// /// \ingroup CreationGroup /// Implementation of the CreationPolicy used by SingletonHolder - /// Creates objects using a straight call to the new operator + /// Creates objects using a straight call to the new operator //////////////////////////////////////////////////////////////////////////////// template <class T> struct CreateUsingNew { static T* Create() { return new T; } - + static void Destroy(T* p) { delete p; } }; - + //////////////////////////////////////////////////////////////////////////////// /// \struct CreateUsing /// @@ -265,13 +267,13 @@ } }; }; - + //////////////////////////////////////////////////////////////////////////////// /// \struct CreateUsingMalloc /// /// \ingroup CreationGroup /// Implementation of the CreationPolicy used by SingletonHolder - /// Creates objects using a call to std::malloc, followed by a call to the + /// Creates objects using a call to std::malloc, followed by a call to the /// placement new operator //////////////////////////////////////////////////////////////////////////////// template <class T> struct CreateUsingMalloc @@ -282,30 +284,30 @@ if (!p) return 0; return new(p) T; } - + static void Destroy(T* p) { p->~T(); std::free(p); } }; - + //////////////////////////////////////////////////////////////////////////////// /// \struct CreateStatic /// /// \ingroup CreationGroup /// Implementation of the CreationPolicy used by SingletonHolder /// Creates an object in static memory - /// Implementation is slightly nonportable because it uses the MaxAlign trick - /// (an union of all types to ensure proper memory alignment). This trick is + /// Implementation is slightly nonportable because it uses the MaxAlign trick + /// (an union of all types to ensure proper memory alignment). This trick is /// nonportable in theory but highly portable in practice. //////////////////////////////////////////////////////////////////////////////// template <class T> struct CreateStatic { - + #ifdef _MSC_VER -#pragma warning( push ) +#pragma warning( push ) #pragma warning( disable : 4121 ) // alignment of a member was sensitive to packing #endif // _MSC_VER @@ -323,17 +325,17 @@ int Test::* pMember_; int (Test::*pMemberFn_)(int); }; - + #ifdef _MSC_VER #pragma warning( pop ) #endif // _MSC_VER - + static T* Create() { static MaxAlign staticMemory_; return new(&staticMemory_) T; } - + static void Destroy(T* p) { p->~T(); @@ -353,7 +355,7 @@ { static void ScheduleDestruction(T*, atexit_pfn_t pFun) { std::atexit(pFun); } - + static void OnDeadReference() { throw std::logic_error("Dead Reference Detected"); } }; @@ -363,7 +365,7 @@ /// /// \ingroup LifetimeGroup /// Implementation of the LifetimePolicy used by SingletonHolder - /// Schedules an object's destruction as per C++ rules, and it allows object + /// Schedules an object's destruction as per C++ rules, and it allows object /// recreation by not throwing an exception from OnDeadReference //////////////////////////////////////////////////////////////////////////////// template <class T> @@ -377,20 +379,20 @@ #endif std::atexit(pFun); } - + static void OnDeadReference() { #ifndef ATEXIT_FIXED destroyedOnce_ = true; #endif } - + private: #ifndef ATEXIT_FIXED static bool destroyedOnce_; #endif }; - + #ifndef ATEXIT_FIXED template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false; #endif @@ -402,13 +404,13 @@ /// /// \ingroup LifetimeGroup /// - /// A DeletableSingleton allows the instantiated singleton to be - /// destroyed at any time. The singleton can be reinstantiated at + /// A DeletableSingleton allows the instantiated singleton to be + /// destroyed at any time. The singleton can be reinstantiated at /// any time, even during program termination. - /// If the singleton exists when the program terminates, it will + /// If the singleton exists when the program terminates, it will /// be automatically deleted. /// - /// \par Usage: + /// \par Usage: /// The singleton can be deleted manually: /// /// DeletableSingleton<MyClass>::GracefulDelete(); @@ -430,9 +432,9 @@ needCallback = false; } } - + static void OnDeadReference() - { + { } /// delete singleton object manually static void GracefulDelete() @@ -442,12 +444,12 @@ isDead = true; deleter(); } - + protected: static atexit_pfn_t deleter; static bool isDead; static bool needCallback; - + static void atexitCallback() { #ifdef ATEXIT_FIXED @@ -458,13 +460,13 @@ GracefulDelete(); } }; - + template <class T> atexit_pfn_t DeletableSingleton<T>::deleter = 0; - + template <class T> bool DeletableSingleton<T>::isDead = true; - + template <class T> bool DeletableSingleton<T>::needCallback = true; @@ -501,7 +503,7 @@ Private::Adapter<T> adapter = { pFun }; SetLongevity(pObj, GetLongevity(pObj), adapter); } - + static void OnDeadReference() { throw std::logic_error("Dead Reference Detected"); } }; @@ -518,12 +520,12 @@ { static void ScheduleDestruction(T*, atexit_pfn_t) {} - + static void OnDeadReference() {} }; - + //////////////////////////////////////////////////////////////////////////////// /// \defgroup LongevityLifetimeGroup LongevityLifetime /// \ingroup LifetimeGroup @@ -537,7 +539,7 @@ namespace LongevityLifetime { //////////////////////////////////////////////////////////////////////////////// - /// \struct SingletonFixedLongevity + /// \struct SingletonFixedLongevity /// /// \ingroup LongevityLifetimeGroup /// Add your own lifetimes into the namespace 'LongevityLifetime' @@ -551,13 +553,13 @@ { public: virtual ~SingletonFixedLongevity() {} - + static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun) { Private::Adapter<T> adapter = { pFun }; SetLongevity(pObj, Longevity , adapter); } - + static void OnDeadReference() { throw std::logic_error("Dead Reference Detected"); } }; @@ -578,11 +580,11 @@ /// \struct DieFirst /// \ingroup LongevityLifetimeGroup - /// \brief Shortest possible SingletonWithLongevity lifetime: 0 + /// \brief Shortest possible SingletonWithLongevity lifetime: 0 template <class T> struct DieFirst : SingletonFixedLongevity<0,T> {}; - + }//namespace LongevityLifetime //////////////////////////////////////////////////////////////////////////////// @@ -590,12 +592,12 @@ /// /// \ingroup LifetimeGroup /// - /// Lifetime policyfor the SingletonHolder tempalte. + /// Lifetime policyfor the SingletonHolder tempalte. /// Followers will die after the master dies Followers will not die, if /// - master never dies (NoDestroy policy) /// - master never created /// - master dies not in the function registered with atexit - /// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete) + /// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete) /// /// \par Usage: /// @@ -611,7 +613,7 @@ typedef std::vector<atexit_pfn_t> Container; typedef typename Container::iterator iterator; static Container* followers_; - + public: static void Init() { @@ -633,7 +635,7 @@ { Init(); for(iterator it = followers_->begin();it != followers_->end();++it) - (*it)(); + (*it)(); delete followers_; } }; @@ -641,7 +643,7 @@ public: /// \struct With - /// Template for the master + /// Template for the master /// \param Lifetime Lifetime policy for the master template<template <class> class Lifetime> struct With @@ -656,7 +658,7 @@ Followers<Master>::Init(); Lifetime<Master>::ScheduleDestruction(pObj, pFun); - // use same policy for the followers and force a new + // use same policy for the followers and force a new // template instantiation, this adds a additional atexit entry // does not work with SetLonlevity, but there you can control // the lifetime with the GetLongevity function. @@ -664,8 +666,8 @@ } static void OnDeadReference() - { - throw std::logic_error("Dead Reference Detected"); + { + throw std::logic_error("Dead Reference Detected"); } }; }; @@ -677,7 +679,7 @@ struct AfterMaster { /// \struct IsDestroyed - /// Policy for followers + /// Policy for followers template<class F> struct IsDestroyed { @@ -685,33 +687,33 @@ { Followers<Master>::AddFollower(pFun); } - + static void OnDeadReference() - { - throw std::logic_error("Dead Reference Detected"); + { + throw std::logic_error("Dead Reference Detected"); } }; }; }; template<class T> - typename FollowIntoDeath::Followers<T>::Container* + typename FollowIntoDeath::Followers<T>::Container* FollowIntoDeath::Followers<T>::followers_ = 0; - - - + + + //////////////////////////////////////////////////////////////////////////////// /// \class SingletonHolder /// /// \ingroup SingletonGroup /// /// Provides Singleton amenities for a type T - /// To protect that type from spurious instantiations, + /// To protect that type from spurious instantiations, /// you have to protect it yourself. - /// + /// /// \param CreationPolicy Creation policy, default: CreateUsingNew /// \param LifetimePolicy Lifetime policy, default: DefaultLifetime, - /// \param ThreadingModel Threading policy, + /// \param ThreadingModel Threading policy, /// default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL //////////////////////////////////////////////////////////////////////////////// template @@ -731,21 +733,21 @@ /// Returns a reference to singleton object static T& Instance(); - + private: // Helpers static void MakeInstance(); static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton(); - + // Protection SingletonHolder(); - + // Data typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType; static PtrInstanceType pInstance_; static bool destroyed_; }; - + //////////////////////////////////////////////////////////////////////////////// // SingletonHolder's data //////////////////////////////////////////////////////////////////////////////// @@ -783,7 +785,7 @@ template <class, class> class ThreadingModel, class MutexPolicy > - inline T& SingletonHolder<T, CreationPolicy, + inline T& SingletonHolder<T, CreationPolicy, LifetimePolicy, ThreadingModel, MutexPolicy>::Instance() { if (!pInstance_) @@ -805,12 +807,12 @@ template <class, class> class ThreadingModel, class MutexPolicy > - void SingletonHolder<T, CreationPolicy, + void SingletonHolder<T, CreationPolicy, LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance() { typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard; (void)guard; - + if (!pInstance_) { if (destroyed_) @@ -819,7 +821,7 @@ destroyed_ = false; } pInstance_ = CreationPolicy<T>::Create(); - LifetimePolicy<T>::ScheduleDestruction(pInstance_, + LifetimePolicy<T>::ScheduleDestruction(pInstance_, &DestroySingleton); } } @@ -832,7 +834,7 @@ template <class, class> class M, class X > - void LOKI_C_CALLING_CONVENTION_QUALIFIER + void LOKI_C_CALLING_CONVENTION_QUALIFIER SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton() { assert(!destroyed_); @@ -849,7 +851,7 @@ /// /// Convenience template to implement a getter function for a singleton object. /// Often needed in a shared library which hosts singletons. - /// + /// /// \par Usage /// /// see test/SingletonDll This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 01:16:35
|
Revision: 1084 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1084&view=rev Author: rich_sposato Date: 2011-06-21 01:16:29 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Renamed template parameter to avoid confusion. Modified Paths: -------------- trunk/include/loki/CheckReturn.h Modified: trunk/include/loki/CheckReturn.h =================================================================== --- trunk/include/loki/CheckReturn.h 2011-06-21 01:11:50 UTC (rev 1083) +++ trunk/include/loki/CheckReturn.h 2011-06-21 01:16:29 UTC (rev 1084) @@ -109,13 +109,13 @@ -template < class Value , template<class> class OnError = TriggerAssert > +template < class ValueType , template<class> class OnError = TriggerAssert > class CheckReturn { public: /// Conversion constructor changes Value type to CheckReturn type. - inline CheckReturn( const Value & value ) : + inline CheckReturn( const ValueType & value ) : m_value( value ), m_checked( false ) {} /// Copy-constructor allows functions to call another function within the @@ -131,11 +131,11 @@ // If m_checked is false, then a function failed to check the // return value from a function call. if (!m_checked) - OnError<Value>::run(m_value); + OnError< ValueType >::run(m_value); } /// Conversion operator changes CheckReturn back to Value type. - inline operator Value ( void ) + inline operator ValueType ( void ) { m_checked = true; return m_value; @@ -149,7 +149,7 @@ CheckReturn & operator = ( const CheckReturn & that ); /// Copy of returned value. - Value m_value; + ValueType m_value; /// Flag for whether calling function checked return value yet. mutable bool m_checked; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 01:11:57
|
Revision: 1083 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1083&view=rev Author: rich_sposato Date: 2011-06-21 01:11:50 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Added test for exception handling policies. Modified Paths: -------------- trunk/test/ScopeGuard/main.cpp Modified: trunk/test/ScopeGuard/main.cpp =================================================================== --- trunk/test/ScopeGuard/main.cpp 2011-06-21 01:07:22 UTC (rev 1082) +++ trunk/test/ScopeGuard/main.cpp 2011-06-21 01:11:50 UTC (rev 1083) @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2006 Peter K�mmel -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// @@ -20,6 +20,11 @@ #include <iostream> #include <assert.h> +using namespace Loki; + + +// ---------------------------------------------------------------------------- + void HasNone( void ) { } @@ -59,9 +64,9 @@ (void)p5; } -void Decrement( unsigned int & x ) -{ - --x; +void Decrement( unsigned int & x ) +{ + --x; } struct UserDatabase @@ -87,7 +92,7 @@ size_t countFriends() const; void DoSomething() const; - + unsigned int fCount; void HasNone( void ) const; @@ -167,7 +172,7 @@ void User::AddFriend(User& newFriend) { - ::Loki::ScopeGuard invariantGuard = ::Loki::MakeObjGuard( *this, + ScopeGuard invariantGuard = MakeObjGuard( *this, &User::CheckIfValid, __FUNCTION__, __LINE__ ); (void)invariantGuard; friends_.push_back(&newFriend); @@ -177,15 +182,15 @@ void User::AddFriendGuarded(User& newFriend) { - ::Loki::ScopeGuard invariantGuard = ::Loki::MakeObjGuard( *this, + ScopeGuard invariantGuard = MakeObjGuard( *this, &User::CheckIfValid, __FUNCTION__, __LINE__ ); (void)invariantGuard; - ::Loki::ScopeGuard guard1 = ::Loki::MakeObjGuard( *this, &User::DoSomething ); + ScopeGuard guard1 = MakeObjGuard( *this, &User::DoSomething ); (void)guard1; friends_.push_back(&newFriend); Loki::ScopeGuard guard = Loki::MakeObjGuard(friends_, &UserCont::pop_back); - + fCount++; Loki::ScopeGuard guardRef = Loki::MakeGuard(Decrement, Loki::ByRef(fCount)); @@ -196,7 +201,7 @@ void User::AddFriendGuardedMacros(User&) { - ::Loki::ScopeGuard invariantGuard = ::Loki::MakeObjGuard( *this, + ScopeGuard invariantGuard = MakeObjGuard( *this, &User::CheckIfValid, __FUNCTION__, __LINE__ ); (void)invariantGuard; LOKI_ON_BLOCK_EXIT_OBJ(friends_, &UserCont::pop_back); (void) LOKI_ANONYMOUS_VARIABLE(scopeGuard); @@ -211,12 +216,12 @@ void DoStandaloneFunctionTests() { - ::Loki::ScopeGuard guard0 = ::Loki::MakeGuard( &HasNone ); - ::Loki::ScopeGuard guard1 = ::Loki::MakeGuard( &HasOne, 1 ); - ::Loki::ScopeGuard guard2 = ::Loki::MakeGuard( &HasTwo, 1, 2 ); - ::Loki::ScopeGuard guard3 = ::Loki::MakeGuard( &HasThree, 1, 2, 3 ); - ::Loki::ScopeGuard guard4 = ::Loki::MakeGuard( &HasFour, 1, 2, 3, 4 ); - ::Loki::ScopeGuard guard5 = ::Loki::MakeGuard( &HasFive, 1, 2, 3, 4, 5 ); + ScopeGuard guard0 = MakeGuard( &HasNone ); + ScopeGuard guard1 = MakeGuard( &HasOne, 1 ); + ScopeGuard guard2 = MakeGuard( &HasTwo, 1, 2 ); + ScopeGuard guard3 = MakeGuard( &HasThree, 1, 2, 3 ); + ScopeGuard guard4 = MakeGuard( &HasFour, 1, 2, 3, 4 ); + ScopeGuard guard5 = MakeGuard( &HasFive, 1, 2, 3, 4, 5 ); (void)guard0; (void)guard1; (void)guard2; @@ -227,16 +232,296 @@ void DoMemberFunctionTests( User & user ) { - ::Loki::ScopeGuard guard0 = ::Loki::MakeObjGuard( user, &User::HasNone ); - ::Loki::ScopeGuard guard1 = ::Loki::MakeObjGuard( user, &User::HasOne, 1 ); - ::Loki::ScopeGuard guard2 = ::Loki::MakeObjGuard( user, &User::HasTwo, 1, 2 ); - ::Loki::ScopeGuard guard3 = ::Loki::MakeObjGuard( user, &User::HasThree, 1, 2, 3 ); + ScopeGuard guard0 = MakeObjGuard( user, &User::HasNone ); + ScopeGuard guard1 = MakeObjGuard( user, &User::HasOne, 1 ); + ScopeGuard guard2 = MakeObjGuard( user, &User::HasTwo, 1, 2 ); + ScopeGuard guard3 = MakeObjGuard( user, &User::HasThree, 1, 2, 3 ); (void)guard0; (void)guard1; (void)guard2; (void)guard3; } +// ---------------------------------------------------------------------------- + +void CalledAlways( void ) +{ + const bool anyThrown = ::std::uncaught_exception(); + const char * message = ( anyThrown ) ? "thrown" : "not thrown"; + ::std::cout << __FUNCTION__ << " Exception was " << message << ::std::endl; +} + +// ---------------------------------------------------------------------------- + +void CalledIfNoException( void ) +{ + const bool anyThrown = ::std::uncaught_exception(); + const char * message = ( anyThrown ) ? "thrown" : "not thrown"; + ::std::cout << __FUNCTION__ << " Exception was " << message << ::std::endl; +} + +// ---------------------------------------------------------------------------- + +void CalledIfException( void ) +{ + const bool anyThrown = ::std::uncaught_exception(); + const char * message = ( anyThrown ) ? "thrown" : "not thrown"; + ::std::cout << __FUNCTION__ << " Exception was " << message << ::std::endl; +} + +// ---------------------------------------------------------------------------- + +void FunctionMightThrow( bool willThrow ) +{ + if ( willThrow ) + throw ::std::exception(); +} + +// ---------------------------------------------------------------------------- + +void DoExceptionTests( void ) +{ + ::std::cout << ::std::endl; + + { + try + { + ::std::cout << "The function should be called." << ::std::endl; + ScopeGuard guard = MakeGuard( &CalledAlways ); + (void)guard; + FunctionMightThrow( false ); + } + catch ( ... ) + { + ::std::cout << "Caught exception." << ::std::endl; + assert( false ); + } + } + + ::std::cout << ::std::endl; + + { + try + { + ::std::cout << "The function should be called." << ::std::endl; + ScopeGuard guard = MakeGuard( &CalledAlways ); + (void)guard; + FunctionMightThrow( true ); + assert( false ); + } + catch ( ... ) + { + ::std::cout << "Caught exception." << ::std::endl; + } + } + + ::std::cout << ::std::endl; + + { + try + { + ::std::cout << "The function should be called." << ::std::endl; + ScopeGuard guard = MakeGuard( &CalledIfNoException ); + guard.SetExceptionPolicy( ScopeGuardImplBase::CallIfNoException ); + FunctionMightThrow( false ); + ::std::cout << "No exception thrown." << ::std::endl; + } + catch ( ... ) + { + ::std::cout << "Caught exception." << ::std::endl; + assert( false ); + } + } + + ::std::cout << ::std::endl; + + { + try + { + ::std::cout << "The function should not be called." << ::std::endl; + ScopeGuard guard = MakeGuard( &CalledIfNoException ); + guard.SetExceptionPolicy( ScopeGuardImplBase::CallIfNoException ); + FunctionMightThrow( true ); + assert( false ); + } + catch ( ... ) + { + ::std::cout << "Caught exception." << ::std::endl; + } + } + + ::std::cout << ::std::endl; + + { + try + { + ::std::cout << "The function should not be called." << ::std::endl; + ScopeGuard guard = MakeGuard( &CalledIfException ); + guard.SetExceptionPolicy( ScopeGuardImplBase::CallIfException ); + FunctionMightThrow( false ); + ::std::cout << "No exception thrown." << ::std::endl; + } + catch ( ... ) + { + ::std::cout << "Caught exception." << ::std::endl; + assert( false ); + } + } + + ::std::cout << ::std::endl; + + { + try + { + ::std::cout << "The function should be called." << ::std::endl; + ScopeGuard guard = MakeGuard( &CalledIfException ); + guard.SetExceptionPolicy( ScopeGuardImplBase::CallIfException ); + FunctionMightThrow( true ); + assert( false ); + } + catch ( ... ) + { + ::std::cout << "Caught exception." << ::std::endl; + } + } + + ::std::cout << ::std::endl; +} + +// ---------------------------------------------------------------------------- + +class Junk +{ +public: + + Junk( void ); + ~Junk( void ); + + bool IsUgly( void ) const; + + bool IsUseful( void ) const; + +}; + +// ---------------------------------------------------------------------------- + +Junk::Junk( void ) +{ + assert( NULL != this ); +} + +// ---------------------------------------------------------------------------- + +Junk::~Junk( void ) +{ + assert( NULL != this ); +} + +// ---------------------------------------------------------------------------- + +bool Junk::IsUgly( void ) const +{ + assert( NULL != this ); + return true; +} + +// ---------------------------------------------------------------------------- + +bool Junk::IsUseful( void ) const +{ + assert( NULL != this ); + return true; +} + +// ---------------------------------------------------------------------------- + +class Attic +{ +public: + + Attic( void ); + ~Attic( void ); + + Junk * RemoveUselessJunk( void ); + +private: + + typedef ::std::vector< Junk * > JunkPile; + typedef JunkPile::iterator JunkPileIter; + + void CheckInvariants( const char * function, unsigned int line ) const; + + void CallObservers( void ) const; + + void EliminateHoles( void ); + + JunkPile m_storage; + +}; + +// ---------------------------------------------------------------------------- + +Attic::Attic( void ) : + m_storage() +{ +} + +// ---------------------------------------------------------------------------- + +Attic::~Attic( void ) +{ +} + +// ---------------------------------------------------------------------------- + +Junk * Attic::RemoveUselessJunk( void ) +{ + ScopeGuard callGuard = MakeObjGuard( *this, &Attic::CallObservers ); + ScopeGuard testGuard = MakeObjGuard( *this, &Attic::CheckInvariants, __FUNCTION__, __LINE__ ); + ScopeGuard fixGuard = MakeObjGuard( *this, &Attic::EliminateHoles ); + callGuard.SetExceptionPolicy( ScopeGuardImplBase::CallIfNoException ); + (void)testGuard; + (void)fixGuard; + + for ( JunkPileIter it( m_storage.begin() ); + it != m_storage.end(); + ++it ) + { + Junk * junk = *it; + if ( junk->IsUgly() ) + return junk; + if ( junk->IsUseful() ) + continue; + delete junk; + *it = NULL; + } + + return NULL; +} + +// ---------------------------------------------------------------------------- + +void Attic::CheckInvariants( const char * function, unsigned int line ) const +{ + assert( NULL != this ); + (void)function; + (void)line; +} + +// ---------------------------------------------------------------------------- + +void Attic::CallObservers( void ) const +{ +} + +// ---------------------------------------------------------------------------- + +void Attic::EliminateHoles( void ) +{ +} + +// ---------------------------------------------------------------------------- + int main() { UserDatabase db; @@ -256,6 +541,7 @@ DoStandaloneFunctionTests(); DoMemberFunctionTests( u1 ); + DoExceptionTests(); #if defined(__BORLANDC__) || defined(_MSC_VER) system("PAUSE"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-06-21 01:07:29
|
Revision: 1082 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1082&view=rev Author: rich_sposato Date: 2011-06-21 01:07:22 +0000 (Tue, 21 Jun 2011) Log Message: ----------- Added ExceptionPolicy enum. Modified Paths: -------------- trunk/include/loki/ScopeGuard.h Modified: trunk/include/loki/ScopeGuard.h =================================================================== --- trunk/include/loki/ScopeGuard.h 2010-10-30 03:12:56 UTC (rev 1081) +++ trunk/include/loki/ScopeGuard.h 2011-06-21 01:07:22 UTC (rev 1082) @@ -4,12 +4,12 @@ // Copyright (c) 2000 Petru Marginean // Copyright (c) 2005 Joshua Lehrer // -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_SCOPEGUARD_INC_ @@ -17,6 +17,7 @@ // $Id$ +#include <exception> // needed for calls to uncaught_exception. #include <loki/RefToValue.h> @@ -42,6 +43,30 @@ class ScopeGuardImplBase { + + public: + + enum ExceptionPolicy + { + AlwaysExecute = 0, + CallIfNoException = 1, + CallIfException = 2 + }; + + ScopeGuardImplBase() throw() : dismissed_(false), exceptionPolicy_( AlwaysExecute ) + {} + + void Dismiss() const throw() + { + dismissed_ = true; + } + + void SetExceptionPolicy( ExceptionPolicy policy ) const throw() + { + exceptionPolicy_ = policy; + } + + private: /// Copy-assignment operator is not implemented and private. ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); @@ -51,34 +76,42 @@ {} /// Copy-constructor takes over responsibility from other ScopeGuard. - ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() + ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() : dismissed_(other.dismissed_) + , exceptionPolicy_( other.exceptionPolicy_ ) { other.Dismiss(); } template <typename J> - static void SafeExecute(J& j) throw() + static void SafeExecute(J& j) throw() { + if ( AlwaysExecute != j.exceptionPolicy_ ) + { + const bool anyThrown = ::std::uncaught_exception(); + if ( anyThrown ) + { + if ( CallIfNoException == j.exceptionPolicy_ ) + j.Dismiss(); + } + else if ( CallIfException == j.exceptionPolicy_ ) + { + j.Dismiss(); + } + } if (!j.dismissed_) + { try { j.Execute(); } catch(...) {} + } } - + mutable bool dismissed_; - - public: - ScopeGuardImplBase() throw() : dismissed_(false) - {} - - void Dismiss() const throw() - { - dismissed_ = true; - } + mutable ExceptionPolicy exceptionPolicy_; }; //////////////////////////////////////////////////////////////// @@ -113,24 +146,24 @@ return ScopeGuardImpl0<F>(fun); } - ~ScopeGuardImpl0() throw() + ~ScopeGuardImpl0() throw() { SafeExecute(*this); } - void Execute() + void Execute() { fun_(); } protected: - ScopeGuardImpl0(F fun) : fun_(fun) + ScopeGuardImpl0(F fun) : fun_(fun) {} F fun_; }; - template <typename F> + template <typename F> inline ScopeGuardImpl0<F> MakeGuard(F fun) { return ScopeGuardImpl0<F>::MakeGuard(fun); @@ -160,7 +193,7 @@ return ScopeGuardImpl1<F, P1>(fun, p1); } - ~ScopeGuardImpl1() throw() + ~ScopeGuardImpl1() throw() { SafeExecute(*this); } @@ -171,14 +204,14 @@ } protected: - ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) + ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) {} F fun_; const P1 p1_; }; - template <typename F, typename P1> + template <typename F, typename P1> inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) { return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1); @@ -208,7 +241,7 @@ return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2); } - ~ScopeGuardImpl2() throw() + ~ScopeGuardImpl2() throw() { SafeExecute(*this); } @@ -219,7 +252,7 @@ } protected: - ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) + ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) {} F fun_; @@ -257,7 +290,7 @@ return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3); } - ~ScopeGuardImpl3() throw() + ~ScopeGuardImpl3() throw() { SafeExecute(*this); } @@ -268,7 +301,7 @@ } protected: - ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) + ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) {} F fun_; @@ -308,7 +341,7 @@ return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 ); } - ~ScopeGuardImpl4() throw() + ~ScopeGuardImpl4() throw() { SafeExecute( *this ); } @@ -361,7 +394,7 @@ return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 ); } - ~ScopeGuardImpl5() throw() + ~ScopeGuardImpl5() throw() { SafeExecute( *this ); } @@ -415,18 +448,18 @@ return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun); } - ~ObjScopeGuardImpl0() throw() + ~ObjScopeGuardImpl0() throw() { SafeExecute(*this); } - void Execute() + void Execute() { (obj_.*memFun_)(); } protected: - ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) + ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) {} Obj& obj_; @@ -440,13 +473,13 @@ } template <typename Ret, class Obj1, class Obj2> - inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) + inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) { return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun); } template <typename Ret, class Obj1, class Obj2> - inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) + inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) { return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun); } @@ -477,20 +510,20 @@ return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1); } - ~ObjScopeGuardImpl1() throw() + ~ObjScopeGuardImpl1() throw() { SafeExecute(*this); } - void Execute() + void Execute() { (obj_.*memFun_)(p1_); } protected: - ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) + ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) {} - + Obj& obj_; MemFun memFun_; const P1 p1_; @@ -503,13 +536,13 @@ } template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> - inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) + inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) { return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1); } template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> - inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) + inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) { return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1); } @@ -540,18 +573,18 @@ return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2); } - ~ObjScopeGuardImpl2() throw() + ~ObjScopeGuardImpl2() throw() { SafeExecute(*this); } - void Execute() + void Execute() { (obj_.*memFun_)(p1_, p2_); } protected: - ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) + ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} Obj& obj_; @@ -567,13 +600,13 @@ } template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> - inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) + inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) { return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2); } template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> - inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) + inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) { return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2); } @@ -605,12 +638,12 @@ return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 ); } - ~ObjScopeGuardImpl3() throw() + ~ObjScopeGuardImpl3() throw() { SafeExecute( *this ); } - void Execute() + void Execute() { ( obj_.*memFun_ )( p1_, p2_, p3_ ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-10-30 03:13:03
|
Revision: 1081 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1081&view=rev Author: rich_sposato Date: 2010-10-30 03:12:56 +0000 (Sat, 30 Oct 2010) Log Message: ----------- Added tests for new single-owner policy classes for StrongPtr. Modified Paths: -------------- trunk/test/SmartPtr/strong.cpp Modified: trunk/test/SmartPtr/strong.cpp =================================================================== --- trunk/test/SmartPtr/strong.cpp 2010-10-30 03:11:07 UTC (rev 1080) +++ trunk/test/SmartPtr/strong.cpp 2010-10-30 03:12:56 UTC (rev 1081) @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Test program for The Loki Library // Copyright (c) 2006 Richard Sposato -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The authors make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The authors make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// @@ -23,12 +23,21 @@ #include <iostream> #include <cassert> +#include <cstring> #include "base.h" // ---------------------------------------------------------------------------- +#if !defined( NULL ) + #define nullptr 0 +#endif + +#if !defined( nullptr ) + #define nullptr NULL +#endif + using namespace std; using namespace Loki; @@ -140,6 +149,7 @@ AssertCheck, AllowReset, DeleteSingle, DontPropagateConst > Moon_StrongPtr; + // ---------------------------------------------------------------------------- class Earth @@ -329,6 +339,8 @@ const unsigned int ctorCount = Counted::GetCtorCount(); const unsigned int dtorCount = Counted::GetDtorCount(); assert( Counted::AllDestroyed() ); + (void)ctorCount; + (void)dtorCount; { Counted_WeakPtr pWeakInt; @@ -1028,11 +1040,591 @@ // ---------------------------------------------------------------------------- +class Ball +{ +public: + + inline static unsigned int GetCtorCount( void ) + { + return s_CtorCount; + } + + inline static unsigned int GetDtorCount( void ) + { + return s_DtorCount; + } + + inline static bool AllDestroyed( void ) + { + return ( s_CtorCount == s_DtorCount ); + } + + inline Ball( void ) + { + s_CtorCount++; + } + + inline ~Ball( void ) + { + s_DtorCount++; + } + +private: + static unsigned int s_CtorCount; + static unsigned int s_DtorCount; +}; + +unsigned int Ball::s_CtorCount = 0; +unsigned int Ball::s_DtorCount = 0; + +// ---------------------------------------------------------------------------- + +// These typedefs are for testing StrongPtr ownership policies that enforce a single owner. +typedef ::Loki::StrongPtr< Ball, false, ::Loki::SingleOwnerRefCount, + ::Loki::DisallowConversion, ::Loki::AssertCheck, ::Loki::OnlyStrongMayReset > + NonOwner_Counted_BallPtr; +typedef ::Loki::StrongPtr< Ball, true, ::Loki::SingleOwnerRefCount, + ::Loki::DisallowConversion, ::Loki::AssertCheck, ::Loki::OnlyStrongMayReset > + Owner_Counted_BallPtr; + +typedef ::Loki::StrongPtr< Ball, false, ::Loki::Lockable1OwnerRefCount, + ::Loki::DisallowConversion, ::Loki::AssertCheck, ::Loki::OnlyStrongMayReset > + Lockable_NonOwner_Counted_BallPtr; +typedef ::Loki::StrongPtr< Ball, true, ::Loki::Lockable1OwnerRefCount, + ::Loki::DisallowConversion, ::Loki::AssertCheck, ::Loki::OnlyStrongMayReset > + Lockable_Owner_Counted_BallPtr; + +typedef ::Loki::StrongPtr< Ball, false, ::Loki::SingleOwnerRefLinks, + ::Loki::DisallowConversion, ::Loki::AssertCheck, ::Loki::OnlyStrongMayReset > + NonOwner_Linked_BallPtr; +typedef ::Loki::StrongPtr< Ball, true, ::Loki::SingleOwnerRefLinks, + ::Loki::DisallowConversion, ::Loki::AssertCheck, ::Loki::OnlyStrongMayReset > + Owner_Linked_BallPtr; + +// ---------------------------------------------------------------------------- + +template < class OwnerPtr, class NonOwnerPtr > +class TheOwner +{ +public: + + TheOwner( void ) : m_myBall(), m_otherBall() {} + ~TheOwner( void ) {} + + void ClearBall( void ) + { + Ball * pBall = NULL; + ResetAll( m_myBall, pBall ); + } + + bool OwnBall( const NonOwnerPtr & ball ) + { + if ( !ball ) + return false; + m_myBall = ball; + return true; + } + + bool OwnBall( const OwnerPtr & ball ) + { + if ( !ball ) + return false; + m_myBall = ball; + return true; + } + + bool OwnBall( Ball * ball ) + { + if ( nullptr == ball ) + return false; + m_myBall = ball; + return true; + } + + bool DoesOwnBall( void ) const + { + const bool hasBall = m_myBall; + return hasBall; + } + + void UseBall( const OwnerPtr & ball ) + { + m_otherBall = ball; + } + + bool DoesUseBall( void ) const + { + const bool hasBall = m_otherBall; + return hasBall; + } + + const OwnerPtr & ShareMyBall( void ) const + { + return m_myBall; + } + + const NonOwnerPtr & ShareOtherBall( void ) + { + return m_otherBall; + } + +private: + OwnerPtr m_myBall; + NonOwnerPtr m_otherBall; +}; + +typedef TheOwner< Owner_Counted_BallPtr, NonOwner_Counted_BallPtr > Toddler; + +typedef TheOwner< Owner_Linked_BallPtr, NonOwner_Linked_BallPtr > Kitten; + +typedef TheOwner< Lockable_Owner_Counted_BallPtr, Lockable_NonOwner_Counted_BallPtr > Teenager; + +// ---------------------------------------------------------------------------- + +template < class OwnerPtr, class NonOwnerPtr, class Owner > +void DoSingleOwnerTest( OwnerPtr & op1, + const NonOwnerPtr & pBall1, + const NonOwnerPtr & pBall2, + const NonOwnerPtr & pBall3, + Owner & owner1, + Owner & owner2, + Owner & owner3 ) +{ + + assert( !pBall1.IsStrong() ); + assert( !pBall2.IsStrong() ); + assert( !pBall3.IsStrong() ); + assert( pBall1 != nullptr ); + assert( pBall2 != nullptr ); + assert( pBall3 != nullptr ); + + assert( !owner1.DoesOwnBall() ); + assert( !owner2.DoesOwnBall() ); + assert( !owner3.DoesOwnBall() ); + assert( !owner1.DoesUseBall() ); + assert( !owner2.DoesUseBall() ); + assert( !owner3.DoesUseBall() ); + + owner1.OwnBall( pBall1 ); + owner2.OwnBall( pBall2 ); + owner3.OwnBall( pBall3 ); + assert( owner1.DoesOwnBall() ); + assert( owner2.DoesOwnBall() ); + assert( owner3.DoesOwnBall() ); + assert( !owner1.DoesUseBall() ); + assert( !owner2.DoesUseBall() ); + assert( !owner3.DoesUseBall() ); + + assert( owner1.ShareMyBall() == pBall1 ); + assert( owner2.ShareMyBall() == pBall2 ); + assert( owner3.ShareMyBall() == pBall3 ); + assert( owner1.ShareMyBall().IsStrong() ); + assert( owner2.ShareMyBall().IsStrong() ); + assert( owner3.ShareMyBall().IsStrong() ); + + owner1.UseBall( owner2.ShareMyBall() ); + owner2.UseBall( owner3.ShareMyBall() ); + owner3.UseBall( owner1.ShareMyBall() ); + assert( owner1.DoesUseBall() ); + assert( owner2.DoesUseBall() ); + assert( owner3.DoesUseBall() ); + + assert( !owner1.ShareOtherBall().IsStrong() ); + assert( !owner2.ShareOtherBall().IsStrong() ); + assert( !owner3.ShareOtherBall().IsStrong() ); + + assert( owner1.ShareOtherBall() == pBall2 ); + assert( owner2.ShareOtherBall() == pBall3 ); + assert( owner3.ShareOtherBall() == pBall1 ); + assert( owner1.ShareMyBall() == pBall1 ); + assert( owner2.ShareMyBall() == pBall2 ); + assert( owner3.ShareMyBall() == pBall3 ); + + try + { + assert( owner2.ShareMyBall() == pBall2 ); + // Can owner1 own a ball that is owned by somebody else? + owner1.OwnBall( pBall2 ); + assert( false ); + } + catch ( const ::std::logic_error & ex ) + { + assert( true ); + assert( ::strcmp( ex.what(), ::Loki::StrongPtr_Single_Owner_Exception_Message ) == 0 ); + (void)ex; + } + try + { + assert( owner3.ShareMyBall() == pBall3 ); + // Can owner2 own a ball that is owned by somebody else? + owner2.OwnBall( pBall3 ); + assert( false ); + } + catch ( const ::std::logic_error & ex ) + { + assert( true ); + assert( ::strcmp( ex.what(), ::Loki::StrongPtr_Single_Owner_Exception_Message ) == 0 ); + (void)ex; + } + try + { + assert( owner1.ShareMyBall() == pBall1 ); + // Can owner3 own a ball that is owned by somebody else? + owner3.OwnBall( pBall1 ); + assert( false ); + } + catch ( const ::std::logic_error & ex ) + { + assert( true ); + assert( ::strcmp( ex.what(), ::Loki::StrongPtr_Single_Owner_Exception_Message ) == 0 ); + (void)ex; + } + + // These tests occur after exceptions were thrown. Since these tests pass, + // that means the pointers are still in a valid state. Also, the pointers + // are untouched by the temporary StrongPtr's that were made inside the + // assignment operators, so therefore the pointers have strong exception + // safety. + owner1.ClearBall(); + owner2.ClearBall(); + owner3.ClearBall(); + assert( !owner1.DoesOwnBall() ); + assert( !owner2.DoesOwnBall() ); + assert( !owner3.DoesOwnBall() ); + assert( nullptr == pBall1 ); + assert( nullptr == pBall2 ); + assert( nullptr == pBall3 ); + assert( owner1.ShareMyBall() == pBall1 ); + assert( owner2.ShareMyBall() == pBall2 ); + assert( owner3.ShareMyBall() == pBall3 ); + assert( owner1.ShareMyBall() == nullptr ); + assert( owner2.ShareMyBall() == nullptr ); + assert( owner3.ShareMyBall() == nullptr ); + + { + Ball * baseball = new Ball; + Ball * football = new Ball; + Ball * softball = new Ball; + + NonOwnerPtr p1( baseball ); + NonOwnerPtr p2( football ); + NonOwnerPtr p3( softball ); + assert( nullptr != p1 ); + assert( nullptr != p2 ); + assert( nullptr != p3 ); + + assert( !p1.IsStrong() ); + assert( !p2.IsStrong() ); + assert( !p3.IsStrong() ); + + { + Owner o1; + Owner o2; + Owner o3; + + assert( !o1.DoesOwnBall() ); + assert( !o2.DoesOwnBall() ); + assert( !o3.DoesOwnBall() ); + assert( !o1.DoesUseBall() ); + assert( !o2.DoesUseBall() ); + assert( !o3.DoesUseBall() ); + + o1.OwnBall( p1 ); + o2.OwnBall( p2 ); + o3.OwnBall( p3 ); + + assert( o1.DoesOwnBall() ); + assert( o2.DoesOwnBall() ); + assert( o3.DoesOwnBall() ); + assert( !o1.DoesUseBall() ); + assert( !o2.DoesUseBall() ); + assert( !o3.DoesUseBall() ); + + assert( o1.ShareMyBall() == p1 ); + assert( o2.ShareMyBall() == p2 ); + assert( o3.ShareMyBall() == p3 ); + + o1.ClearBall(); + o2.ClearBall(); + o3.ClearBall(); + assert( !o1.DoesOwnBall() ); + assert( !o2.DoesOwnBall() ); + assert( !o3.DoesOwnBall() ); + assert( o1.ShareMyBall() == nullptr ); + assert( o2.ShareMyBall() == nullptr ); + assert( o3.ShareMyBall() == nullptr ); + assert( nullptr == p1 ); + assert( nullptr == p2 ); + assert( nullptr == p3 ); + assert( o1.ShareMyBall() == p1 ); + assert( o2.ShareMyBall() == p2 ); + assert( o3.ShareMyBall() == p3 ); + } + + assert( Ball::AllDestroyed() ); + assert( nullptr == p1 ); + assert( nullptr == p2 ); + assert( nullptr == p3 ); + } + + { + OwnerPtr op_1; + OwnerPtr op_2; + (void)op_1; + (void)op_2; + op_1 = op_2; + } + assert( Ball::AllDestroyed() ); + + // Test ResetAll with owner pointer. + { + Ball * ball = new Ball; + Ball * noBall = nullptr; + OwnerPtr op_1( ball ); + NonOwnerPtr np1( op_1 ); + NonOwnerPtr np2( np1 ); + assert( ball == op_1 ); + assert( ball == np1 ); + assert( ball == np2 ); + + ResetAll( op_1, noBall ); + assert( Ball::AllDestroyed() ); + assert( nullptr == op_1 ); + assert( nullptr == np1 ); + assert( nullptr == np2 ); + assert( nullptr == noBall ); + } + + // Test ReleaseAll with owner pointer. + { + Ball * ball = new Ball; + Ball * noBall = nullptr; + OwnerPtr op_1( ball ); + NonOwnerPtr np1( op_1 ); + NonOwnerPtr np2( np1 ); + assert( ball == op_1 ); + assert( ball == np1 ); + assert( ball == np2 ); + + ReleaseAll( op_1, noBall ); + assert( !Ball::AllDestroyed() ); + assert( nullptr != noBall ); + assert( noBall == ball ); + assert( nullptr == op_1 ); + assert( nullptr == np1 ); + assert( nullptr == np2 ); + delete noBall; + assert( Ball::AllDestroyed() ); + } + + // Test ResetAll with nonowner pointer. + { + Ball * ball = new Ball; + Ball * noBall = nullptr; + OwnerPtr op_1( ball ); + NonOwnerPtr np1( op_1 ); + NonOwnerPtr np2( np1 ); + assert( ball == op_1 ); + assert( ball == np1 ); + assert( ball == np2 ); + + ResetAll( np1, noBall ); + // ResetAll fails for non-owner pointers. + assert( !Ball::AllDestroyed() ); + assert( nullptr != op_1 ); + assert( nullptr != np1 ); + assert( nullptr != np2 ); + assert( nullptr == noBall ); + } + assert( Ball::AllDestroyed() ); + + // Test ReleaseAll with nonowner pointer. + { + Ball * ball = new Ball; + Ball * noBall = nullptr; + OwnerPtr op_1( ball ); + NonOwnerPtr np1( op_1 ); + NonOwnerPtr np2( np1 ); + assert( ball == op_1 ); + assert( ball == np1 ); + assert( ball == np2 ); + + ReleaseAll( np1, noBall ); + // ReleaseAll fails for non-owner pointers. + assert( !Ball::AllDestroyed() ); + assert( nullptr != op_1 ); + assert( nullptr != np1 ); + assert( nullptr != np2 ); + assert( nullptr == noBall ); + } + assert( Ball::AllDestroyed() ); + + // Test assignment operator. + { + OwnerPtr op2; + Ball * ball1 = new Ball; + Ball * ball2 = new Ball; + op1 = ball1; + op2 = ball2; + assert( ball1 == op1 ); + assert( ball2 == op2 ); + op1 = nullptr; + } + assert( Ball::AllDestroyed() ); + + // Test the Swap function for strong co-pointers. + { + NonOwnerPtr np1; + NonOwnerPtr np2; + Ball * ball1 = new Ball; + Ball * ball2 = new Ball; + np1 = ball1; + np2 = ball2; + assert( ball1 == np1 ); + assert( ball2 == np2 ); + assert( nullptr != np1 ); + assert( nullptr != np2 ); + + op1 = np1; + OwnerPtr op2( np2 ); + assert( np1 == op1 ); + assert( np2 == op2 ); + assert( np2 != op1 ); + assert( np1 != op2 ); + + op1.Swap( op2 ); + + assert( ball1 != op1 ); // Owners do not point to original objects. + assert( ball2 != op2 ); + assert( ball2 == op1 ); // Owners now point to different objects. + assert( ball1 == op2 ); + assert( ball1 != np2 ); // Non-owners still point to original objects. + assert( ball2 != np1 ); + assert( ball2 == np2 ); // Non-owners do not point to different objects. + assert( ball1 == np1 ); + assert( np1 != op1 ); + assert( np2 != op2 ); + assert( np2 == op1 ); + assert( np1 == op2 ); + assert( nullptr != op1 ); + assert( nullptr != op2 ); + assert( nullptr != np1 ); + assert( nullptr != np2 ); + op1 = nullptr; + } + assert( Ball::AllDestroyed() ); + + // Test the Swap function for weak co-pointers. + { + NonOwnerPtr np1; + NonOwnerPtr np2; + Ball * ball1 = new Ball; + Ball * ball2 = new Ball; + np1 = ball1; + np2 = ball2; + assert( ball1 == np1 ); + assert( ball2 == np2 ); + assert( nullptr != np1 ); + assert( nullptr != np2 ); + + op1 = np1; + OwnerPtr op2( np2 ); + assert( np1 == op1 ); + assert( np2 == op2 ); + assert( np2 != op1 ); + assert( np1 != op2 ); + + np1.Swap( np2 ); + + assert( ball1 == op1 ); // Owners still point to their original objects. + assert( ball2 == op2 ); + assert( ball2 != op1 ); // Owners do not point to different objects. + assert( ball1 != op2 ); + assert( ball1 == np2 ); // Non-owners now point to different objects. + assert( ball2 == np1 ); + assert( ball2 != np2 ); // Non-owners do not point to their original objects. + assert( ball1 != np1 ); + assert( np1 != op1 ); + assert( np2 != op2 ); + assert( np2 == op1 ); + assert( np1 == op2 ); + assert( nullptr != op1 ); + assert( nullptr != op2 ); + assert( nullptr != np1 ); + assert( nullptr != np2 ); + op1 = nullptr; + } + assert( Ball::AllDestroyed() ); + + // A Swap of a weak pointer with a strong pointer will cause a compiler error. +} + +// ---------------------------------------------------------------------------- + +void DoSingleOwnerTests( void ) +{ + + // These tests exercise the lockable single-owner StrongPtr policies. + { + Ball * baseball = new Ball; + Ball * football = new Ball; + Ball * softball = new Ball; + Lockable_Owner_Counted_BallPtr op1; + Lockable_NonOwner_Counted_BallPtr pBaseball( baseball ); + Lockable_NonOwner_Counted_BallPtr pFootball( football ); + Lockable_NonOwner_Counted_BallPtr pSoftball( softball ); + Teenager teen1; + Teenager teen2; + Teenager teen3; + DoSingleOwnerTest( op1, pBaseball, pFootball, pSoftball, + teen1, teen2, teen3 ); + } + assert( Ball::AllDestroyed() ); + + // These tests exercise the reference-counted single-owner StrongPtr policies. + { + Ball * soccerBall = new Ball; + Ball * bouncyBall = new Ball; + Ball * basketBall = new Ball; + + NonOwner_Counted_BallPtr pSoccerBall( soccerBall ); + NonOwner_Counted_BallPtr pBouncyBall( bouncyBall ); + NonOwner_Counted_BallPtr pBasketBall( basketBall ); + Toddler child1; + Toddler child2; + Toddler child3; + Owner_Counted_BallPtr op1; + DoSingleOwnerTest( op1, pSoccerBall, pBouncyBall, pBasketBall, + child1, child2, child3 ); + } + assert( Ball::AllDestroyed() ); + + // These tests exercise the linked-cycle single-owner StrongPtr policies. + { + Ball * yarnBall = new Ball; + Ball * twineBall = new Ball; + Ball * stringBall = new Ball; + + NonOwner_Linked_BallPtr pYarnBall( yarnBall ); + NonOwner_Linked_BallPtr pTwineBall( twineBall ); + NonOwner_Linked_BallPtr pStringBall( stringBall ); + Kitten cat1; + Kitten cat2; + Kitten cat3; + Owner_Linked_BallPtr op1; + DoSingleOwnerTest( op1, pYarnBall, pTwineBall, pStringBall, + cat1, cat2, cat3 ); + } + assert( Ball::AllDestroyed() ); +} + +// ---------------------------------------------------------------------------- + void DoStrongForwardReferenceTest( void ) { /** @note These lines should cause the compiler to make a warning message about attempting to delete an undefined type. They should also cause - an error message about a negative subscript since + an error message about a negative subscript since */ //Thingy_DeleteSingle_ptr p1; //Thingy_DeleteSingle_ptr p2( p1 ); @@ -1064,15 +1656,15 @@ { }; typedef Loki::StrongPtr -< +< BaseClass, false, TwoRefCounts, DisallowConversion, - AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst + AssertCheck, CantResetWithStrong, DeleteSingle, DontPropagateConst > Ptr; bool Compare( const Ptr&, const Ptr&) { - return true; + return true; } void friend_handling2() @@ -1497,6 +2089,3 @@ // this will not compile: //int i = f1.i; } - - - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-10-30 03:11:13
|
Revision: 1080 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1080&view=rev Author: rich_sposato Date: 2010-10-30 03:11:07 +0000 (Sat, 30 Oct 2010) Log Message: ----------- Added 3 new policy classes to support single-owner smart pointers. Fixed 2 obscure bugs in TwoRefLinks policy. Modified Paths: -------------- trunk/src/StrongPtr.cpp Modified: trunk/src/StrongPtr.cpp =================================================================== --- trunk/src/StrongPtr.cpp 2010-10-30 03:09:25 UTC (rev 1079) +++ trunk/src/StrongPtr.cpp 2010-10-30 03:11:07 UTC (rev 1080) @@ -33,8 +33,44 @@ namespace Loki { +namespace Private +{ + // ---------------------------------------------------------------------------- +OneOwnerRefCountInfo::OneOwnerRefCountInfo( SingleOwnerRefCount * ptr ) + : m_pointer( NULL ) + , m_strongPtr( ptr ) + , m_weakCount( ( NULL == ptr ) ? 1 : 0 ) +{ + assert( NULL != this ); +} + +// ---------------------------------------------------------------------------- + +OneOwnerRefCountInfo::OneOwnerRefCountInfo( const void * p, + SingleOwnerRefCount * ptr ) + : m_pointer( p ) + , m_strongPtr( ptr ) + , m_weakCount( ( NULL == ptr ) ? 1 : 0 ) +{ + assert( NULL != this ); +} + +// ---------------------------------------------------------------------------- + +void OneOwnerRefCountInfo::SetStrongCoPtr( SingleOwnerRefCount * ptr ) +{ + assert( NULL != this ); + m_strongPtr = ptr; +} + +// ---------------------------------------------------------------------------- + +} // end namespace Private + +// ---------------------------------------------------------------------------- + TwoRefCounts::TwoRefCounts( bool strong ) : m_counts( NULL ) { @@ -111,7 +147,7 @@ void TwoRefCounts::Swap( TwoRefCounts & rhs ) { - std::swap( m_counts, rhs.m_counts ); + ::std::swap( m_counts, rhs.m_counts ); } // ---------------------------------------------------------------------------- @@ -133,18 +169,174 @@ } } +// ---------------------------------------------------------------------------- +SingleOwnerRefCount::SingleOwnerRefCount( bool strong ) + : m_info( NULL ) +{ + assert( NULL != this ); + + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::OneOwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + SingleOwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) ::Loki::Private::OneOwnerRefCountInfo( ptr ); +} + // ---------------------------------------------------------------------------- +SingleOwnerRefCount::SingleOwnerRefCount( const void * p, bool strong ) + : m_info( NULL ) +{ + assert( NULL != this ); + + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::OneOwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + SingleOwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) ::Loki::Private::OneOwnerRefCountInfo( p, ptr ); +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefCount::SingleOwnerRefCount( const SingleOwnerRefCount & rhs, + bool strong ) + : m_info( NULL ) +{ + assert( NULL != this ); + + if ( strong && rhs.HasStrongPointer() ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + m_info = rhs.m_info; + if ( strong ) + { + m_info->SetStrongCoPtr( this ); + } + else + { + m_info->IncWeakCount(); + } +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefCount::SingleOwnerRefCount( const SingleOwnerRefCount & rhs, + bool isNull, bool strong ) + : m_info( NULL ) +{ + assert( NULL != this ); + + if ( isNull ) + { + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::OneOwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + SingleOwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) ::Loki::Private::OneOwnerRefCountInfo( ptr ); + return; + } + + if ( strong && rhs.HasStrongPointer() ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + m_info = rhs.m_info; + if ( strong ) + { + m_info->SetStrongCoPtr( this ); + } + else + { + m_info->IncWeakCount(); + } +} + +// ---------------------------------------------------------------------------- + +void SingleOwnerRefCount::Swap( SingleOwnerRefCount & rhs ) +{ + assert( NULL != this ); + + if ( IsStrong() && rhs.IsStrong() ) + { + // These two strong pointers are trading resources. + SingleOwnerRefCount * temp = rhs.m_info->GetStrongCoPointer(); + rhs.m_info->SetStrongCoPtr( this ); + m_info->SetStrongCoPtr( temp ); + } + ::std::swap( m_info, rhs.m_info ); +} + +// ---------------------------------------------------------------------------- + +bool SingleOwnerRefCount::Release( bool strong ) +{ + assert( NULL != this ); + + assert( strong == IsStrong() ); + if ( strong ) + { + m_info->SetStrongCoPtr( NULL ); + return true; + } + + assert( 0 < m_info->GetWeakCount() ); + m_info->DecWeakCount(); + const bool noOwner = ( !m_info->HasStrongPointer() ); + return ( ( 0 == m_info->GetWeakCount() ) && noOwner ); +} + +// ---------------------------------------------------------------------------- + +void SingleOwnerRefCount::ZapPointer( void ) +{ + assert( !m_info->HasStrongPointer() ); + if ( m_info->HasWeakPointer() ) + { + m_info->ZapPointer(); + } + else + { + SmallObject<>::operator delete ( m_info, + sizeof(Loki::Private::OneOwnerRefCountInfo) ); + m_info = NULL; + } +} + +// ---------------------------------------------------------------------------- + +void SingleOwnerRefCount::SetPointer( void * p ) +{ + assert( NULL != this ); + if ( IsStrong() || ( 1 == m_info->GetWeakCount() ) ) + { + // Only a strong pointer or the last weak pointer may change a resource. + m_info->SetPointer( p ); + } +} + +// ---------------------------------------------------------------------------- + TwoRefLinks::TwoRefLinks( const void * p, bool strong ) : m_pointer( const_cast< void * >( p ) ) , m_strong( strong ) , m_prev( this ) , m_next( this ) { -#ifdef DO_EXTRA_LOKI_TESTS - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); -#endif + assert( IsValid() ); } // ---------------------------------------------------------------------------- @@ -159,14 +351,11 @@ m_next->m_prev = this; #ifdef DO_EXTRA_LOKI_TESTS - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); assert( rhs.m_next->HasNextNode( this ) ); assert( rhs.m_prev->HasPrevNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); assert( CountPrevCycle( this ) == CountNextCycle( &rhs ) ); - assert( AllNodesHaveSamePointer() ); #endif + assert( IsValid() ); } // ---------------------------------------------------------------------------- @@ -177,6 +366,8 @@ , m_next( ( isNull ) ? 0 : rhs.m_next ) , m_strong( strong ) { + assert( rhs.IsValid() ); + if ( isNull ) { m_prev = m_next = this; @@ -185,77 +376,66 @@ { m_prev->m_next = this; m_next->m_prev = this; - -#ifdef DO_EXTRA_LOKI_TESTS - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); assert( rhs.m_next->HasNextNode( this ) ); assert( rhs.m_prev->HasPrevNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); assert( CountPrevCycle( this ) == CountNextCycle( &rhs ) ); - assert( AllNodesHaveSamePointer() ); -#endif } + assert( IsValid() ); } // ---------------------------------------------------------------------------- +TwoRefLinks::~TwoRefLinks( void ) +{ + assert( IsValid() ); + + if ( ( NULL != m_prev ) && ( this != m_prev ) ) + { + TwoRefLinks * next = m_next; + m_prev->m_next = next; + m_next->m_prev = m_prev; + } +} + +// ---------------------------------------------------------------------------- + void TwoRefLinks::SetPointer( void * p ) { - TwoRefLinks * node = m_prev; - if ( ( this == node ) || ( 0 == node ) ) + assert( IsValid() ); + + TwoRefLinks * node = m_next; + if ( ( this == node ) || ( NULL == node ) ) + { + m_pointer = p; return; + } -#ifdef DO_EXTRA_LOKI_TESTS - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); - assert( AllNodesHaveSamePointer() ); -#endif - while ( node != this ) { node->m_pointer = p; node = node->m_next; } - m_pointer = node; + m_pointer = p; -#ifdef DO_EXTRA_LOKI_TESTS - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); - assert( AllNodesHaveSamePointer() ); -#endif + assert( IsValid() ); } // ---------------------------------------------------------------------------- bool TwoRefLinks::Release( bool strong ) { - + assert( IsValid() ); + assert( strong == m_strong ); (void)strong; -#ifdef DO_EXTRA_LOKI_TESTS - assert( strong == m_strong ); - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); - assert( AllNodesHaveSamePointer() ); -#endif if ( NULL == m_next ) { -#ifdef DO_EXTRA_LOKI_TESTS - assert( NULL == m_prev ); -#endif // Return false so it does not try to destroy shared object // more than once. return false; } - else if (m_next == this) + else if ( m_next == this ) { -#ifdef DO_EXTRA_LOKI_TESTS - assert(m_prev == this); -#endif // Set these to NULL to prevent re-entrancy. m_prev = NULL; m_next = NULL; @@ -263,22 +443,21 @@ return true; } -#ifdef DO_EXTRA_LOKI_TESTS assert( this != m_prev ); assert( NULL != m_prev ); - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); -#endif - // If a single node is strong, then return false so it won't release. if ( HasStrongPointer() ) { // A cyclic chain of pointers is only as strong as the strongest link. m_prev->m_next = m_next; m_next->m_prev = m_prev; + m_next = this; + m_prev = this; + assert( IsValid() ); return false; } + assert( IsValid() ); return true; } @@ -286,8 +465,10 @@ void TwoRefLinks::ZapAllNodes( void ) { + assert( IsValid() ); + TwoRefLinks * p = m_prev; - if ( ( this == p ) || ( 0 == p ) ) + if ( ( this == p ) || ( NULL == p ) ) return; #ifdef DO_EXTRA_LOKI_TESTS assert( AllNodesHaveSamePointer() ); @@ -296,28 +477,28 @@ while ( p != this ) { TwoRefLinks * p1 = p->m_prev; - p->m_pointer = 0; + p->m_pointer = NULL; p->m_next = p; p->m_prev = p; p = p1; } - m_pointer = 0; + m_pointer = NULL; + m_next = this; + m_prev = this; + + assert( IsValid() ); } // ---------------------------------------------------------------------------- void TwoRefLinks::Swap( TwoRefLinks & rhs ) { + assert( IsValid() ); + assert( rhs.IsValid() ); + if ( GetPointer() == rhs.GetPointer() ) + return; -#ifdef DO_EXTRA_LOKI_TESTS - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); - assert( AllNodesHaveSamePointer() ); - assert( rhs.AllNodesHaveSamePointer() ); -#endif - - std::swap( rhs.m_pointer, m_pointer ); + ::std::swap( rhs.m_pointer, m_pointer ); if (m_next == this) { #ifdef DO_EXTRA_LOKI_TESTS @@ -376,19 +557,8 @@ std::swap(m_next->m_prev, rhs.m_next->m_prev); } -#ifdef DO_EXTRA_LOKI_TESTS - assert( m_next == this ? m_prev == this : m_prev != this); - assert( m_prev == this ? m_next == this : m_next != this); - assert( m_prev->HasPrevNode( this ) ); - assert( m_next->HasNextNode( this ) ); - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); - assert( rhs.m_prev->HasPrevNode( &rhs ) ); - assert( rhs.m_next->HasNextNode( &rhs ) ); - assert( CountPrevCycle( &rhs ) == CountNextCycle( &rhs ) ); - assert( AllNodesHaveSamePointer() ); - assert( rhs.AllNodesHaveSamePointer() ); -#endif - + assert( IsValid() ); + assert( rhs.IsValid() ); } // ---------------------------------------------------------------------------- @@ -457,6 +627,7 @@ { if ( this == p ) return true; + const TwoRefLinks * prev = m_prev; if ( NULL == prev ) return false; @@ -475,6 +646,7 @@ { if ( this == p ) return true; + const TwoRefLinks * next = m_next; if ( NULL == next ) return false; @@ -491,6 +663,8 @@ bool TwoRefLinks::HasStrongPointer( void ) const { + assert( IsValid() ); + const TwoRefLinks * next = m_next; if ( NULL == next ) return false; @@ -507,12 +681,12 @@ bool TwoRefLinks::Merge( TwoRefLinks & rhs ) { + assert( IsValid() ); + assert( rhs.IsValid() ); if ( NULL == m_next ) { -#ifdef DO_EXTRA_LOKI_TESTS assert( NULL == m_prev ); -#endif return false; } TwoRefLinks * prhs = &rhs; @@ -520,14 +694,11 @@ return true; if ( NULL == prhs->m_next ) { -#ifdef DO_EXTRA_LOKI_TESTS assert( NULL == prhs->m_prev ); -#endif return true; } #ifdef DO_EXTRA_LOKI_TESTS - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); assert( CountPrevCycle( prhs ) == CountNextCycle( prhs ) ); #endif // If rhs node is already in this cycle, then no need to merge. @@ -542,9 +713,7 @@ if ( prhs == prhs->m_next ) { /// rhs is in a cycle with 1 node. -#ifdef DO_EXTRA_LOKI_TESTS assert( prhs->m_prev == prhs ); -#endif prhs->m_prev = m_prev; prhs->m_next = this; m_prev->m_next = prhs; @@ -553,9 +722,7 @@ else if ( this == m_next ) { /// this is in a cycle with 1 node. -#ifdef DO_EXTRA_LOKI_TESTS assert( m_prev == this ); -#endif m_prev = prhs->m_prev; m_next = prhs; prhs->m_prev->m_next = this; @@ -571,7 +738,7 @@ #ifdef DO_EXTRA_LOKI_TESTS - assert( CountPrevCycle( this ) == CountNextCycle( this ) ); + assert( IsValid() ); #endif return true; @@ -579,6 +746,230 @@ // ---------------------------------------------------------------------------- +unsigned int TwoRefLinks::GetStrongPointerCount( void ) const +{ + assert( IsValid() ); + + unsigned int strongCount = ( m_strong ) ? 1 : 0; + const TwoRefLinks * next = m_next; + if ( ( this == next ) || ( NULL == next ) ) + return strongCount; + + while ( next != this ) + { + if ( next->m_strong ) + { + ++strongCount; + } + next = next->m_next; + } + + return strongCount; +} + +// ---------------------------------------------------------------------------- + +const TwoRefLinks * TwoRefLinks::GetNextStrongPointer( void ) const +{ + assert( IsValid() ); + + for ( const TwoRefLinks * next = m_next; + ( next != this ); next = next->m_next ) + { + if ( next->m_strong ) + { + return next; + } + } + + return this; +} + +// ---------------------------------------------------------------------------- + +bool TwoRefLinks::IsValid( void ) const +{ + assert( NULL != this ); + + const bool isThisNext = ( m_next == this ); + const bool isThisPrev = ( m_prev == this ); + assert( isThisNext == isThisPrev ); + (void)isThisNext; + (void)isThisPrev; + + const bool isNextNull = ( m_next == NULL ); + const bool isPrevNull = ( m_prev == NULL ); + assert( isNextNull == isPrevNull ); + (void)isNextNull; + (void)isPrevNull; + + if ( NULL != m_prev ) + { + assert( NULL != m_next ); + assert( this == m_next->m_prev ); + assert( this == m_prev->m_next ); + assert( m_prev->HasPrevNode( this ) ); + } + if ( NULL != m_next ) + { + assert( NULL != m_prev ); + assert( this == m_next->m_prev ); + assert( this == m_prev->m_next ); + assert( m_next->HasNextNode( this ) ); + } + const unsigned int prevCycleCount = CountPrevCycle( this ); + const unsigned int nextCycleCount = CountNextCycle( this ); + assert( prevCycleCount == nextCycleCount ); + (void)prevCycleCount; + (void)nextCycleCount; + + assert( AllNodesHaveSamePointer() ); + + return true; +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefLinks::SingleOwnerRefLinks( bool strong ) + : TwoRefLinks( strong ) +{ + assert( NULL != this ); + const unsigned int strongCount = GetStrongPointerCount(); + if ( 1 < strongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefLinks::SingleOwnerRefLinks( const void * p, bool strong ) + : TwoRefLinks( p, strong ) +{ + assert( NULL != this ); + const unsigned int strongCount = GetStrongPointerCount(); + if ( 1 < strongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefLinks::SingleOwnerRefLinks( const SingleOwnerRefLinks & rhs, bool strong ) + : TwoRefLinks( rhs, strong ) +{ + assert( NULL != this ); + const unsigned int strongCount = rhs.GetStrongPointerCount(); + if ( 1 < strongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefLinks::SingleOwnerRefLinks( const SingleOwnerRefLinks & rhs, + bool isNull, bool strong ) + : TwoRefLinks( rhs, isNull, strong ) +{ + assert( NULL != this ); + const unsigned int strongCount = GetStrongPointerCount(); + if ( 1 < strongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } +} + +// ---------------------------------------------------------------------------- + +SingleOwnerRefLinks::~SingleOwnerRefLinks( void ) +{ + assert( NULL != this ); + const unsigned int strongCount = GetStrongPointerCount(); + // Use assert instead of throw inside a destructor. + assert( strongCount < 2 ); + (void)strongCount; +} + +// ---------------------------------------------------------------------------- + +void SingleOwnerRefLinks::Swap( SingleOwnerRefLinks & rhs ) +{ + assert( NULL != this ); + if ( GetPointer() == rhs.GetPointer() ) + return; + + const unsigned int lhsStrongCount = GetStrongPointerCount(); + if ( 1 < lhsStrongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + const unsigned int rhsStrongCount = rhs.GetStrongPointerCount(); + if ( 1 < rhsStrongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + TwoRefLinks::Swap( rhs ); +} + +// ---------------------------------------------------------------------------- + +bool SingleOwnerRefLinks::Merge( SingleOwnerRefLinks & rhs ) +{ + assert( NULL != this ); + + const unsigned int lhsStrongCount = GetStrongPointerCount(); + if ( 1 < lhsStrongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + const unsigned int rhsStrongCount = rhs.GetStrongPointerCount(); + if ( 1 < rhsStrongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + if ( 1 < lhsStrongCount + rhsStrongCount ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + const bool success = TwoRefLinks::Merge( rhs ); + return success; +} + +// ---------------------------------------------------------------------------- + +bool SingleOwnerRefLinks::Release( bool strong ) +{ + assert( NULL != this ); + + if ( strong ) + { + const TwoRefLinks * pStrong = GetNextStrongPointer(); + if ( this != pStrong ) + { + // There is another strong pointer in this linked pointer cycle, + // so just return false to prevent this strong pointer from + // deleting the same resource multiple times. + TwoRefLinks::Release( strong ); + return false; + } + } + + const unsigned int strongCount = GetStrongPointerCount(); + // Use assert instead of throw because Release function only gets called + // from StrongPtr destructor, and destructors must not throw exceptions. + assert( strongCount < 2 ); + (void)strongCount; + + const bool doZap = TwoRefLinks::Release( strong ); + return doZap; +} + +// ---------------------------------------------------------------------------- + #if defined( _MSC_VER ) #pragma warning( pop ) #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-10-30 03:09:32
|
Revision: 1079 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1079&view=rev Author: rich_sposato Date: 2010-10-30 03:09:25 +0000 (Sat, 30 Oct 2010) Log Message: ----------- Added 3 new policy classes to support single-owner smart pointers. Changed how ResetPolicy classes get called. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2010-09-16 17:32:24 UTC (rev 1078) +++ trunk/include/loki/StrongPtr.h 2010-10-30 03:09:25 UTC (rev 1079) @@ -58,9 +58,9 @@ /// -# explicit YourPolicy( bool strong ) /// -# YourPolicy( void * p, bool strong ) /// -# YourPolicy( const YourPolicy & rhs, bool strong ) +/// -# YourPolicy( const YourPolicy & rhs, bool isNull, bool strong ) +/// -# ~YourPolicy( void ) /// -# bool Release( bool strong ) -/// -# void Increment( bool strong ) -/// -# bool Decrement( bool strong ) /// -# bool HasStrongPointer( void ) const /// -# void Swap( YourPolicy & rhs ) /// -# void SetPointer( void * p ) @@ -100,11 +100,11 @@ /// /// \par Writing Your Own ResetPolicy /// If you write your own policy, you must implement these 2 functions: -/// -# bool OnReleaseAll( bool ) const -/// -# bool OnResetAll( bool ) const -/// The bool parameter means that this was called with a strong pointer or -/// one of its copointers is strong. The return value means the pointer -/// can be reset or released. +/// -# bool OnReleaseAll( bool, bool ) const +/// -# bool OnResetAll( bool, bool ) const +/// The first bool parameter is true if the pointer which called the function +/// is strong. The second parameter is true if any copointer is strong. The +/// return value means the pointer can be reset or released. /// /// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies /// \ingroup SmartPointerGroup @@ -118,7 +118,10 @@ namespace Loki { +static const char * const StrongPtr_Single_Owner_Exception_Message = + "Object has more than one Owner - which violates the single owner policy for StrongPtr!"; + //////////////////////////////////////////////////////////////////////////////// /// \class DeleteUsingFree /// @@ -250,18 +253,45 @@ template < class P > struct CantResetWithStrong { - inline bool OnReleaseAll( bool hasStrongPtr ) const + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const { - return ! hasStrongPtr; + (void)isThisStrong; + return ! isAnyStrong; } - inline bool OnResetAll( bool hasStrongPtr ) const + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const { - return ! hasStrongPtr; + (void)isThisStrong; + return ! isAnyStrong; } }; //////////////////////////////////////////////////////////////////////////////// +/// \class OnlyStrongMayReset +/// +/// \ingroup StrongPointerResetGroup +/// Implementation of the ResetPolicy used by StrongPtr. It only allows a +/// a strong co-pointer to reset or release. This policy was made for use with +/// the single-owner policies. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +struct OnlyStrongMayReset +{ + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const + { + (void)isAnyStrong; + return isThisStrong; + } + + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const + { + (void)isAnyStrong; + return isThisStrong; + } +}; + +//////////////////////////////////////////////////////////////////////////////// /// \class AllowReset /// /// \ingroup StrongPointerResetGroup @@ -272,12 +302,16 @@ template < class P > struct AllowReset { - inline bool OnReleaseAll( bool ) const + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return true; } - inline bool OnResetAll( bool ) const + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return true; } }; @@ -293,18 +327,26 @@ template < class P > struct NeverReset { - inline bool OnReleaseAll( bool ) const + inline bool OnReleaseAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return false; } - inline bool OnResetAll( bool ) const + inline bool OnResetAll( bool isThisStrong, bool isAnyStrong ) const { + (void)isThisStrong; + (void)isAnyStrong; return false; } }; // ---------------------------------------------------------------------------- +// Forward declaration needed for pointer to single-owner strong pointer. +class SingleOwnerRefCount; +class Lockable1OwnerRefCount; + namespace Private { @@ -399,6 +441,8 @@ } private: + /// Default constructor not implemented. + TwoRefCountInfo( void ); /// Copy-constructor not implemented. TwoRefCountInfo( const TwoRefCountInfo & ); /// Copy-assignment operator not implemented. @@ -410,6 +454,105 @@ }; //////////////////////////////////////////////////////////////////////////////// +/// \class OneOwnerRefCountInfo +/// +/// \ingroup StrongPointerOwnershipGroup +/// Implementation detail for reference counting strong and weak pointers. +/// It maintains a void pointer and 2 reference counts. Since it is just a +/// class for managing implementation details, it is not intended to be used +/// directly - which is why it is in a private namespace. Each instance is a +/// shared resource for all copointers, and there should be only one of these +/// for each set of copointers. This class is small, trivial, and inline. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT OneOwnerRefCountInfo +{ +public: + + explicit OneOwnerRefCountInfo( SingleOwnerRefCount * ptr ); + + OneOwnerRefCountInfo( const void * p, SingleOwnerRefCount * ptr ); + + inline ~OneOwnerRefCountInfo( void ) + { + assert( NULL == m_strongPtr ); + assert( 0 == m_weakCount ); + } + + inline bool HasStrongPointer( void ) const + { + return ( NULL != m_strongPtr ); + } + + inline const SingleOwnerRefCount * GetStrongCoPointer( void ) const + { + return m_strongPtr; + } + + inline SingleOwnerRefCount * GetStrongCoPointer( void ) + { + return m_strongPtr; + } + + void SetStrongCoPtr( SingleOwnerRefCount * ptr ); + + inline bool HasWeakPointer( void ) const + { + return ( 0 < m_weakCount ); + } + + inline unsigned int GetWeakCount( void ) const + { + return m_weakCount; + } + + inline void IncWeakCount( void ) + { + ++m_weakCount; + } + + inline void DecWeakCount( void ) + { + assert( 0 < m_weakCount ); + --m_weakCount; + } + + inline void ZapPointer( void ) + { + m_pointer = NULL; + } + + void SetPointer( void * p ) + { + m_pointer = p; + } + + inline void * GetPointer( void ) const + { + return const_cast< void * >( m_pointer ); + } + + inline void * & GetPointerRef( void ) const + { + return const_cast< void * & >( m_pointer ); + } + +private: + /// Default constructor not implemented. + OneOwnerRefCountInfo( void ); + /// Copy constructor not implemented. + OneOwnerRefCountInfo( const OneOwnerRefCountInfo & ); + /// Copy-assignment operator not implemented. + OneOwnerRefCountInfo & operator = ( const OneOwnerRefCountInfo & ); + + const void * m_pointer; + SingleOwnerRefCount * m_strongPtr; + unsigned int m_weakCount; +}; + +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + +//////////////////////////////////////////////////////////////////////////////// /// \class LockableTwoRefCountInfo /// /// \ingroup StrongPointerOwnershipGroup @@ -427,8 +570,6 @@ /// do run properly. //////////////////////////////////////////////////////////////////////////////// -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) - class LOKI_EXPORT LockableTwoRefCountInfo : private Loki::Private::TwoRefCountInfo { @@ -540,6 +681,154 @@ mutable LOKI_DEFAULT_MUTEX m_Mutex; }; +//////////////////////////////////////////////////////////////////////////////// +/// \class Lockable1OwnerRefCountInfo +/// +/// \ingroup StrongPointerOwnershipGroup +/// Implementation detail for thread-safe reference counting for 1 strong and +/// multiple weak pointers. It uses OneOwnerRefCountInfo to manage the pointers +/// and count. All this does is provide a thread safety mechanism. Since it +/// is just a class for managing implementation details, it is not intended to +/// be used directly - which is why it is in a private namespace. Each instance +/// is a shared resource for all copointers, and there should be only one of +/// these for each set of copointers. This class is small, trivial, and inline. +/// +/// \note This class is not designed for use with a single-threaded model. +/// Tests using a single-threaded model will not run properly, but tests in a +/// multi-threaded model with either class-level-locking or object-level-locking +/// do run properly. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT Lockable1OwnerRefCountInfo + : private Loki::Private::OneOwnerRefCountInfo +{ +public: + + explicit Lockable1OwnerRefCountInfo( Lockable1OwnerRefCount * ptr ) + : OneOwnerRefCountInfo( reinterpret_cast< SingleOwnerRefCount * >( ptr ) ) + , m_Mutex() + { + } + + Lockable1OwnerRefCountInfo( const void * p, Lockable1OwnerRefCount * ptr ) + : OneOwnerRefCountInfo( p, + reinterpret_cast< SingleOwnerRefCount * >( ptr ) ) + , m_Mutex() + { + } + + inline ~Lockable1OwnerRefCountInfo( void ) + { + } + + inline void Lock( void ) const + { + m_Mutex.Lock(); + } + + inline void Unlock( void ) const + { + m_Mutex.Unlock(); + } + + inline const Lockable1OwnerRefCount * GetStrongCoPointer( void ) const + { + m_Mutex.Lock(); + const SingleOwnerRefCount * ptr = + OneOwnerRefCountInfo::GetStrongCoPointer(); + m_Mutex.Unlock(); + return reinterpret_cast< const Lockable1OwnerRefCount * >( ptr ); + } + + inline Lockable1OwnerRefCount * GetStrongCoPointer( void ) + { + m_Mutex.Lock(); + SingleOwnerRefCount * ptr = OneOwnerRefCountInfo::GetStrongCoPointer(); + m_Mutex.Unlock(); + return reinterpret_cast< Lockable1OwnerRefCount * >( ptr ); + } + + inline void SetStrongCoPtr( Lockable1OwnerRefCount * ptr ) + { + m_Mutex.Lock(); + SingleOwnerRefCount * p = reinterpret_cast< SingleOwnerRefCount * >( ptr ); + OneOwnerRefCountInfo::SetStrongCoPtr( p ); + m_Mutex.Unlock(); + } + + inline bool HasStrongPointer( void ) const + { + m_Mutex.Lock(); + const bool has = OneOwnerRefCountInfo::HasStrongPointer(); + m_Mutex.Unlock(); + return has; + } + + inline unsigned int GetWeakCount( void ) const + { + m_Mutex.Lock(); + const unsigned int weakCount = OneOwnerRefCountInfo::HasWeakPointer(); + m_Mutex.Unlock(); + return weakCount; + } + + inline bool HasWeakPointer( void ) const + { + m_Mutex.Lock(); + const bool has = OneOwnerRefCountInfo::HasWeakPointer(); + m_Mutex.Unlock(); + return has; + } + + inline void IncWeakCount( void ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::IncWeakCount(); + m_Mutex.Unlock(); + } + + inline void DecWeakCount( void ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::DecWeakCount(); + m_Mutex.Unlock(); + } + + inline void ZapPointer( void ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::ZapPointer(); + m_Mutex.Unlock(); + } + + void SetPointer( void * p ) + { + m_Mutex.Lock(); + OneOwnerRefCountInfo::SetPointer( p ); + m_Mutex.Unlock(); + } + + inline void * GetPointer( void ) const + { + return OneOwnerRefCountInfo::GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return OneOwnerRefCountInfo::GetPointerRef(); + } + +private: + /// Default constructor is not available. + Lockable1OwnerRefCountInfo( void ); + /// Copy constructor is not available. + Lockable1OwnerRefCountInfo( const Lockable1OwnerRefCountInfo & ); + /// Copy-assignment operator is not available. + Lockable1OwnerRefCountInfo & operator = ( const Lockable1OwnerRefCountInfo & ); + + mutable LOKI_DEFAULT_MUTEX m_Mutex; +}; + #endif // if object-level-locking or class-level-locking } // end namespace Private @@ -582,7 +871,7 @@ return Decrement( strong ); } - bool HasStrongPointer( void ) const + inline bool HasStrongPointer( void ) const { return m_counts->HasStrongPointer(); } @@ -607,7 +896,12 @@ } private: + + /// Default constructor is not implemented. TwoRefCounts( void ); + /// Copy constructor is not implemented. + TwoRefCounts( const TwoRefCounts & ); + /// Copy-assignment operator is not implemented. TwoRefCounts & operator = ( const TwoRefCounts & ); void Increment( bool strong ); @@ -619,6 +913,93 @@ }; //////////////////////////////////////////////////////////////////////////////// +/// \class SingleOwnerRefCount +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy extends the ownership +/// policy class, TwoRefCounts, to enforce that only one StrongPtr may "own" a +/// resource. The resource is destroyed only when its sole owner dies even if +/// weak pointers access it. The constructors enforce the single-owner policy +/// by throwing a bad_logic exception if more than one strong pointer claims to +/// own the resource. Use this policy when you want the code to specify that +/// only one object owns a resource. +/// +/// \note This class is not designed for use with a multi-threaded model. +/// Tests using a multi-threaded model may not run properly. +/// +/// \note If you use any single-owner class, you should also use the +/// OnlyStrongMayReset class for the ResetPolicy in StrongPtr. +/// +/// \note All single-owner policies do not allow programmers to return a +/// a StrongPtr by value from a function, since that would temporarily create +/// an additional strong co-pointer. Nor can programmers store any strong +/// co-pointers in a container that uses copy-in and copy-out semantics. Once +/// C++ allows for move constructors, these limitations go away. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT SingleOwnerRefCount +{ +protected: + + explicit SingleOwnerRefCount( bool strong ); + + SingleOwnerRefCount( const void * p, bool strong ); + + SingleOwnerRefCount( const SingleOwnerRefCount & rhs, + bool strong ); + + SingleOwnerRefCount( const SingleOwnerRefCount & rhs, + bool isNull, bool strong ); + + /** The destructor should not anything since the call to ZapPointer inside + StrongPtr::~StrongPtr will do the cleanup which this dtor would have done. + By the time the dtor is called, the underlying pointer, m_info, is NULL. + */ + inline ~SingleOwnerRefCount( void ) {} + + bool Release( bool strong ); + + inline bool HasStrongPointer( void ) const + { + return ( NULL != m_info->GetStrongCoPointer() ); + } + + void Swap( SingleOwnerRefCount & rhs ); + + void SetPointer( void * p ); + + void ZapPointer( void ); + + inline void * GetPointer( void ) const + { + return m_info->GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return m_info->GetPointerRef(); + } + +private: + /// Default constructor is not implemented. + SingleOwnerRefCount( void ); + /// Copy constructor is not implemented. + SingleOwnerRefCount( const SingleOwnerRefCount & ); + /// Copy-assignment operator is not implemented. + SingleOwnerRefCount & operator = ( const SingleOwnerRefCount & ); + + inline bool IsStrong( void ) const + { + return ( this == m_info->GetStrongCoPointer() ); + } + + ::Loki::Private::OneOwnerRefCountInfo * m_info; + +}; + +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + +//////////////////////////////////////////////////////////////////////////////// /// \class LockableTwoRefCounts /// /// \ingroup StrongPointerOwnershipGroup @@ -633,8 +1014,6 @@ /// do run properly. //////////////////////////////////////////////////////////////////////////////// -#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) - class LOKI_EXPORT LockableTwoRefCounts { typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator; @@ -744,7 +1123,7 @@ void Swap( LockableTwoRefCounts & rhs ) { - std::swap( m_counts, rhs.m_counts ); + ::std::swap( m_counts, rhs.m_counts ); } void SetPointer( void * p ) @@ -780,13 +1159,250 @@ } private: + /// Default constructor is not implemented. LockableTwoRefCounts( void ); + /// Copy constructor is not implemented. + LockableTwoRefCounts( const LockableTwoRefCounts & ); + /// Copy-assignment operator is not implemented. LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & ); /// Pointer to all shared data. Loki::Private::LockableTwoRefCountInfo * m_counts; }; +//////////////////////////////////////////////////////////////////////////////// +/// \class Lockable1OwnerRefCount +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy extends the ownership +/// policy class, LockableTwoRefCounts, to enforce that only one StrongPtr +/// may "own" a resource. The resource is destroyed only when its sole owner +/// dies regardless of how many weak pointers access it. The constructors +/// enforce the single-owner policy by throwing a bad_logic exception if more +/// than one strong pointer claims to own the resource. Use this policy when +/// you want the code to specify that only one object owns a resource. +/// +/// \note This class is not designed for use with a single-threaded model. +/// Tests using a single-threaded model will not run properly, but tests in a +/// multi-threaded model with either class-level-locking or object-level-locking +/// do run properly. +/// +/// \note If you use any single-owner class, you should also use the +/// OnlyStrongMayReset class for the ResetPolicy in StrongPtr. +/// +/// \note All single-owner policies do not allow programmers to return a +/// a StrongPtr by value from a function, since that would temporarily create +/// an additional strong co-pointer. Nor can programmers store any strong +/// co-pointers in a container that uses copy-in and copy-out semantics. Once +/// C++ allows for move constructors, these limitations go away. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT Lockable1OwnerRefCount +{ + typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator; + +protected: + + explicit Lockable1OwnerRefCount( bool strong ) + : m_info( NULL ) + { + assert( NULL != this ); + + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + Lockable1OwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) + ::Loki::Private::Lockable1OwnerRefCountInfo( ptr ); + } + + Lockable1OwnerRefCount( const void * p, bool strong ) + : m_info( NULL ) + { + assert( NULL != this ); + + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + Lockable1OwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) + ::Loki::Private::Lockable1OwnerRefCountInfo( p, ptr ); + } + + Lockable1OwnerRefCount( const Lockable1OwnerRefCount & rhs, bool strong ) : + m_info( rhs.m_info ) + { + assert( NULL != this ); + + if ( strong && rhs.HasStrongPointer() ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + m_info = rhs.m_info; + if ( strong ) + { + m_info->SetStrongCoPtr( this ); + } + else + { + m_info->IncWeakCount(); + } + } + + Lockable1OwnerRefCount( const Lockable1OwnerRefCount & rhs, + bool isNull, bool strong ) : + m_info( ( isNull ) ? NULL : rhs.m_info ) + { + assert( NULL != this ); + + if ( isNull ) + { + void * temp = SmallObject<>::operator new( + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + + Lockable1OwnerRefCount * ptr = ( strong ) ? this : NULL; + m_info = new ( temp ) + ::Loki::Private::Lockable1OwnerRefCountInfo( ptr ); + return; + } + + if ( strong && rhs.HasStrongPointer() ) + { + throw ::std::logic_error( StrongPtr_Single_Owner_Exception_Message ); + } + + m_info = rhs.m_info; + if ( strong ) + { + m_info->SetStrongCoPtr( this ); + } + else + { + m_info->IncWeakCount(); + } + } + + /** The destructor does not need to do anything since the call to + ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which + this dtor would have done. + */ + inline ~Lockable1OwnerRefCount( void ) {} + + inline void Lock( void ) const + { + m_info->Lock(); + } + + inline void Unlock( void ) const + { + m_info->Unlock(); + } + + inline bool Release( bool strong ) + { + assert( NULL != this ); + assert( strong == IsStrong() ); + + if ( strong ) + { + m_info->SetStrongCoPtr( NULL ); + return true; + } + + m_info->Lock(); + assert( 0 < m_info->GetWeakCount() ); + m_info->DecWeakCount(); + const bool noOwner = ( !m_info->HasStrongPointer() ); + const bool doRelease = ( ( 0 == m_info->GetWeakCount() ) && noOwner ); + m_info->Unlock(); + return doRelease; + } + + bool HasStrongPointer( void ) const + { + return m_info->HasStrongPointer(); + } + + void Swap( Lockable1OwnerRefCount & rhs ) + { + assert( NULL != this ); + m_info->Lock(); + rhs.m_info->Lock(); + + if ( IsStrong() && rhs.IsStrong() ) + { + // These two strong pointers are trading resources. + rhs.m_info->SetStrongCoPtr( this ); + m_info->SetStrongCoPtr( &rhs ); + } + ::std::swap( m_info, rhs.m_info ); + m_info->Unlock(); + rhs.m_info->Unlock(); + } + + void SetPointer( void * p ) + { + assert( NULL != this ); + if ( IsStrong() || ( 1 == m_info->GetWeakCount() ) ) + { + // Only a strong pointer or the last weak pointer may change a resource. + m_info->SetPointer( p ); + } + } + + void ZapPointer( void ) + { + assert( !m_info->HasStrongPointer() ); + if ( m_info->HasWeakPointer() ) + { + m_info->ZapPointer(); + } + else + { + SmallObject<>::operator delete ( m_info, + sizeof(Loki::Private::Lockable1OwnerRefCountInfo) ); + m_info = NULL; + } + } + + inline void * GetPointer( void ) const + { + return m_info->GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return m_info->GetPointerRef(); + } + +private: + /// Default constructor is not implemented. + Lockable1OwnerRefCount( void ); + /// Copy constructor is not implemented. + Lockable1OwnerRefCount( const Lockable1OwnerRefCount & ); + /// Copy-assignment operator is not implemented. + Lockable1OwnerRefCount & operator = ( const Lockable1OwnerRefCount & ); + + inline bool IsStrong( void ) const + { + return ( this == m_info->GetStrongCoPointer() ); + } + + /// Pointer to shared info about resource. + ::Loki::Private::Lockable1OwnerRefCountInfo * m_info; + +}; + #endif // if object-level-locking or class-level-locking //////////////////////////////////////////////////////////////////////////////// @@ -817,14 +1433,21 @@ TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong ); + ~TwoRefLinks( void ); + bool Release( bool strong ); void Swap( TwoRefLinks & rhs ); bool Merge( TwoRefLinks & rhs ); + /// Returns pointer to next link in cycle is a strong pointer. + const TwoRefLinks * GetNextStrongPointer( void ) const; + bool HasStrongPointer( void ) const; + unsigned int GetStrongPointerCount( void ) const; + inline void ZapPointer( void ) { ZapAllNodes(); @@ -842,13 +1465,20 @@ return const_cast< void * & >( m_pointer ); } + inline bool IsStrong( void ) const + { + return m_strong; + } + private: static unsigned int CountPrevCycle( const TwoRefLinks * pThis ); static unsigned int CountNextCycle( const TwoRefLinks * pThis ); - /// Not implemented. + /// Default constructor is not implemented. TwoRefLinks( void ); - /// Not implemented. + /// Copy constructor is not implemented. + TwoRefLinks( const TwoRefLinks & ); + /// Copy-assignment operator is not implemented. TwoRefLinks & operator = ( const TwoRefLinks & ); bool HasPrevNode( const TwoRefLinks * p ) const; @@ -856,6 +1486,8 @@ bool AllNodesHaveSamePointer( void ) const; void ZapAllNodes( void ); + bool IsValid( void ) const; + void * m_pointer; mutable TwoRefLinks * m_prev; mutable TwoRefLinks * m_next; @@ -863,6 +1495,61 @@ }; //////////////////////////////////////////////////////////////////////////////// +/// \class SingleOwnerRefLinks +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy extends the ownership +/// policy class, TwoRefLinks, to enforce that only one StrongPtr may "own" a +/// resource. The resource is destroyed only when its sole owner dies even if +/// weak pointers access it. The constructors enforce the single-owner policy +/// by throwing a bad_logic exception if more than one strong pointer claims to +/// own the resource. Use this policy when you want the code to specify that +/// only one object owns a resource. +/// +/// \note This class is not designed for use with a multi-threaded model. +/// Tests using a multi-threaded model may not run properly. +/// +/// \note If you use any single-owner class, you should also use the +/// OnlyStrongMayReset class for the ResetPolicy in StrongPtr. +/// +/// \note All single-owner policies do not allow programmers to return a +/// a StrongPtr by value from a function, since that would temporarily create +/// an additional strong co-pointer. Nor can programmers store any strong +/// co-pointers in a container that uses copy-in and copy-out semantics. Once +/// C++ allows for move constructors, these limitations go away. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT SingleOwnerRefLinks : public TwoRefLinks +{ +protected: + + explicit SingleOwnerRefLinks( bool strong ); + + SingleOwnerRefLinks( const void * p, bool strong ); + + SingleOwnerRefLinks( const SingleOwnerRefLinks & rhs, bool strong ); + + SingleOwnerRefLinks( const SingleOwnerRefLinks & rhs, bool isNull, bool strong ); + + ~SingleOwnerRefLinks( void ); + + void Swap( SingleOwnerRefLinks & rhs ); + + bool Merge( SingleOwnerRefLinks & rhs ); + + bool Release( bool strong ); + +private: + + /// Default constructor is not implemented. + SingleOwnerRefLinks( void ); + /// Copy constructor is not implemented. + SingleOwnerRefLinks( const SingleOwnerRefLinks & ); + /// Copy-assignment operator is not implemented. + SingleOwnerRefLinks & operator = ( const SingleOwnerRefLinks & ); +}; + +//////////////////////////////////////////////////////////////////////////////// /// \class StrongPtr /// /// \ingroup SmartPointerGroup @@ -880,11 +1567,11 @@ < typename T, bool Strong = true, - class OwnershipPolicy = Loki::TwoRefCounts, - class ConversionPolicy = Loki::DisallowConversion, - template < class > class CheckingPolicy = Loki::AssertCheck, - template < class > class ResetPolicy = Loki::CantResetWithStrong, - template < class > class DeletePolicy = Loki::DeleteSingle, + class OwnershipPolicy = ::Loki::TwoRefCounts, + class ConversionPolicy = ::Loki::DisallowConversion, + template < class > class CheckingPolicy = ::Loki::AssertCheck, + template < class > class ResetPolicy = ::Loki::CantResetWithStrong, + template < class > class DeletePolicy = ::Loki::DeleteSingle, template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS > class StrongPtr @@ -1072,7 +1759,7 @@ return *this; } - bool IsStrong( void ) const + inline bool IsStrong( void ) const { return Strong; } @@ -1159,7 +1846,7 @@ friend bool ReleaseAll( StrongPtr & sp, typename StrongPtr::StoredType & p ) { - if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP::OnReleaseAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } @@ -1175,7 +1862,7 @@ { return true; } - if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } @@ -1498,7 +2185,7 @@ bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp, typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType & p ) { - if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } @@ -1526,7 +2213,7 @@ { return true; } - if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + if ( !sp.RP<T>::OnResetAll( sp.IsStrong(), sp.OP::HasStrongPointer() ) ) { return false; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-16 17:32:30
|
Revision: 1078 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1078&view=rev Author: rich_sposato Date: 2010-09-16 17:32:24 +0000 (Thu, 16 Sep 2010) Log Message: ----------- Used initialization instead of assignment within constructor. Modified Paths: -------------- trunk/include/loki/SmartPtr.h Modified: trunk/include/loki/SmartPtr.h =================================================================== --- trunk/include/loki/SmartPtr.h 2010-09-16 17:28:52 UTC (rev 1077) +++ trunk/include/loki/SmartPtr.h 2010-09-16 17:32:24 UTC (rev 1078) @@ -54,7 +54,12 @@ #define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND #endif +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable: 4355 ) +#endif + namespace Loki { @@ -654,8 +659,9 @@ class LOKI_EXPORT RefLinkedBase { protected: - RefLinkedBase() - { prev_ = next_ = this; } + RefLinkedBase( void ) : + prev_( this ), next_( this ) + {} RefLinkedBase(const RefLinkedBase& rhs); @@ -1869,5 +1875,10 @@ }; } +// ---------------------------------------------------------------------------- + +#if defined( _MSC_VER ) + #pragma warning( pop ) +#endif + #endif // end file guardian - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-16 17:28:59
|
Revision: 1077 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1077&view=rev Author: rich_sposato Date: 2010-09-16 17:28:52 +0000 (Thu, 16 Sep 2010) Log Message: ----------- Used initialization instead of assignment within constructor. Modified Paths: -------------- trunk/include/loki/StrongPtr.h Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2010-09-16 17:26:29 UTC (rev 1076) +++ trunk/include/loki/StrongPtr.h 2010-09-16 17:28:52 UTC (rev 1077) @@ -22,7 +22,12 @@ #include <loki/Threads.h> #endif +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable: 4355 ) +#endif + //////////////////////////////////////////////////////////////////////////////// /// /// \par Terminology @@ -801,8 +806,9 @@ inline explicit TwoRefLinks( bool strong ) : m_pointer( 0 ) , m_strong( strong ) + , m_prev( this ) + , m_next( this ) { - m_prev = m_next = this; } TwoRefLinks( const void * p, bool strong ); @@ -1808,5 +1814,8 @@ //////////////////////////////////////////////////////////////////////////////// +#if defined( _MSC_VER ) + #pragma warning( pop ) +#endif + #endif // end file guardian - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-16 17:26:35
|
Revision: 1076 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1076&view=rev Author: rich_sposato Date: 2010-09-16 17:26:29 +0000 (Thu, 16 Sep 2010) Log Message: ----------- Used initialization instead of assignment within constructor. Modified Paths: -------------- trunk/src/SmartPtr.cpp Modified: trunk/src/SmartPtr.cpp =================================================================== --- trunk/src/SmartPtr.cpp 2010-09-16 17:23:59 UTC (rev 1075) +++ trunk/src/SmartPtr.cpp 2010-09-16 17:26:29 UTC (rev 1076) @@ -3,14 +3,14 @@ // Copyright (c) 2001 by Andrei Alexandrescu // Copyright (c) 2006 Richard Sposato // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// @@ -37,10 +37,10 @@ // ---------------------------------------------------------------------------- -RefLinkedBase::RefLinkedBase(const RefLinkedBase& rhs) +RefLinkedBase::RefLinkedBase( const RefLinkedBase & rhs ) : + prev_( &rhs ), + next_( rhs.next_ ) { - prev_ = &rhs; - next_ = rhs.next_; prev_->next_ = this; next_->prev_ = this; @@ -70,7 +70,7 @@ return false; } else if (next_ == this) - { + { assert(prev_ == this); // Set these to NULL to prevent re-entrancy. prev_ = NULL; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-16 17:24:05
|
Revision: 1075 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1075&view=rev Author: rich_sposato Date: 2010-09-16 17:23:59 +0000 (Thu, 16 Sep 2010) Log Message: ----------- Replaced repeated calculation with local variable. Modified Paths: -------------- trunk/src/SmallObj.cpp Modified: trunk/src/SmallObj.cpp =================================================================== --- trunk/src/SmallObj.cpp 2010-09-16 17:22:53 UTC (rev 1074) +++ trunk/src/SmallObj.cpp 2010-09-16 17:23:59 UTC (rev 1075) @@ -943,18 +943,19 @@ assert( CountEmptyChunks() < 2 ); Chunk * foundChunk = nullptr; - if ( ( nullptr != hint ) && ( hint->HasBlock( p, numBlocks_ * blockSize_ ) ) ) + const ::std::size_t chunkLength = numBlocks_ * blockSize_; + if ( ( nullptr != hint ) && ( hint->HasBlock( p, chunkLength ) ) ) foundChunk = hint; - else if ( deallocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) ) + else if ( deallocChunk_->HasBlock( p, chunkLength ) ) foundChunk = deallocChunk_; - else if ( allocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) ) + else if ( allocChunk_->HasBlock( p, chunkLength ) ) foundChunk = allocChunk_; else foundChunk = VicinityFind( p ); if ( nullptr == foundChunk ) return false; - assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) ); + assert( foundChunk->HasBlock( p, chunkLength ) ); #ifdef LOKI_CHECK_FOR_CORRUPTION if ( foundChunk->IsCorrupt( numBlocks_, blockSize_, true ) ) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-16 17:22:59
|
Revision: 1074 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1074&view=rev Author: rich_sposato Date: 2010-09-16 17:22:53 +0000 (Thu, 16 Sep 2010) Log Message: ----------- Used initialization instead of assignment within constructor. Modified Paths: -------------- trunk/src/StrongPtr.cpp Modified: trunk/src/StrongPtr.cpp =================================================================== --- trunk/src/StrongPtr.cpp 2010-09-08 02:22:28 UTC (rev 1073) +++ trunk/src/StrongPtr.cpp 2010-09-16 17:22:53 UTC (rev 1074) @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2006 Rich Sposato -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// @@ -22,7 +22,12 @@ #include <loki/SmallObj.h> +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable: 4355 ) +#endif + // ---------------------------------------------------------------------------- namespace Loki @@ -134,8 +139,9 @@ TwoRefLinks::TwoRefLinks( const void * p, bool strong ) : m_pointer( const_cast< void * >( p ) ) , m_strong( strong ) + , m_prev( this ) + , m_next( this ) { - m_prev = m_next = this; #ifdef DO_EXTRA_LOKI_TESTS assert( CountPrevCycle( this ) == CountNextCycle( this ) ); #endif @@ -246,7 +252,7 @@ return false; } else if (m_next == this) - { + { #ifdef DO_EXTRA_LOKI_TESTS assert(m_prev == this); #endif @@ -573,5 +579,8 @@ // ---------------------------------------------------------------------------- +#if defined( _MSC_VER ) + #pragma warning( pop ) +#endif + } // end namespace Loki - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-08 02:22:34
|
Revision: 1073 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1073&view=rev Author: rich_sposato Date: 2010-09-08 02:22:28 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Fixed bug 3061653 by adding code to check pointers to chunks before searching. Fixed bug 3061659 by checking for empty list. Modified Paths: -------------- trunk/src/SmallObj.cpp Modified: trunk/src/SmallObj.cpp =================================================================== --- trunk/src/SmallObj.cpp 2010-09-08 01:58:51 UTC (rev 1072) +++ trunk/src/SmallObj.cpp 2010-09-08 02:22:28 UTC (rev 1073) @@ -821,11 +821,24 @@ if ( chunks_.size() == chunks_.capacity() ) return false; - // Use the "make-a-temp-and-swap" trick to remove excess capacity. - Chunks( chunks_ ).swap( chunks_ ); - deallocChunk_ = &chunks_.front(); - allocChunk_ = &chunks_.back(); + { + // Use the "make-a-temp-and-swap" trick to remove excess capacity. + Chunks temp( chunks_ ); + temp.swap( chunks_ ); + } + + if ( chunks_.empty() ) + { + deallocChunk_ = nullptr; + allocChunk_ = nullptr; + } + else + { + deallocChunk_ = &chunks_.front(); + allocChunk_ = &chunks_.back(); + } + return true; } @@ -929,7 +942,15 @@ assert( &chunks_.back() >= allocChunk_ ); assert( CountEmptyChunks() < 2 ); - Chunk * foundChunk = ( nullptr == hint ) ? VicinityFind( p ) : hint; + Chunk * foundChunk = nullptr; + if ( ( nullptr != hint ) && ( hint->HasBlock( p, numBlocks_ * blockSize_ ) ) ) + foundChunk = hint; + else if ( deallocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) ) + foundChunk = deallocChunk_; + else if ( allocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) ) + foundChunk = allocChunk_; + else + foundChunk = VicinityFind( p ); if ( nullptr == foundChunk ) return false; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-08 01:58:57
|
Revision: 1072 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1072&view=rev Author: rich_sposato Date: 2010-09-08 01:58:51 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Some coding style changes. Added namespace resolution. Modified Paths: -------------- trunk/src/SmallObj.cpp Modified: trunk/src/SmallObj.cpp =================================================================== --- trunk/src/SmallObj.cpp 2010-09-08 01:03:21 UTC (rev 1071) +++ trunk/src/SmallObj.cpp 2010-09-08 01:58:51 UTC (rev 1072) @@ -87,7 +87,7 @@ @param blocks Number of blocks per Chunk. @return True for success, false for failure. */ - bool Init( std::size_t blockSize, unsigned char blocks ); + bool Init( ::std::size_t blockSize, unsigned char blocks ); /** Allocate a block within the Chunk. Complexity is always O(1), and this will never throw. Does not actually "allocate" by calling @@ -95,7 +95,7 @@ indexes to indicate an already allocated block is no longer available. @return Pointer to block within Chunk. */ - void * Allocate( std::size_t blockSize ); + void * Allocate( ::std::size_t blockSize ); /** Deallocate a block within the Chunk. Complexity is always O(1), and this will never throw. For efficiency, this assumes the address is @@ -105,14 +105,14 @@ delete, or other function, but merely adjusts some internal indexes to indicate a block is now available. */ - void Deallocate( void * p, std::size_t blockSize ); + void Deallocate( void * p, ::std::size_t blockSize ); /** Resets the Chunk back to pristine values. The available count is set back to zero, and the first available index is set to the zeroth block. The stealth indexes inside each block are set to point to the next block. This assumes the Chunk's data was already using Init. */ - void Reset( std::size_t blockSize, unsigned char blocks ); + void Reset( ::std::size_t blockSize, unsigned char blocks ); /// Releases the allocated block of memory. void Release(); @@ -126,7 +126,7 @@ release version runs faster.) @return True if Chunk is corrupt. */ - bool IsCorrupt( unsigned char numBlocks, std::size_t blockSize, + bool IsCorrupt( unsigned char numBlocks, ::std::size_t blockSize, bool checkIndexes ) const; /** Determines if block is available. @@ -136,10 +136,10 @@ @return True if block is available, else false if allocated. */ bool IsBlockAvailable( void * p, unsigned char numBlocks, - std::size_t blockSize ) const; + ::std::size_t blockSize ) const; /// Returns true if block at address P is inside this Chunk. - inline bool HasBlock( void * p, std::size_t chunkLength ) const + inline bool HasBlock( void * p, ::std::size_t chunkLength ) const { unsigned char * pc = static_cast< unsigned char * >( p ); return ( pData_ <= pc ) && ( pc < pData_ + chunkLength ); @@ -214,7 +214,7 @@ FixedAllocator& operator=(const FixedAllocator&); /// Type of container used to hold Chunks. - typedef std::vector< Chunk > Chunks; + typedef ::std::vector< Chunk > Chunks; /// Iterator through container of Chunks. typedef Chunks::iterator ChunkIter; /// Iterator through const container of Chunks. @@ -227,7 +227,7 @@ static unsigned char MaxObjectsPerChunk_; /// Number of bytes in a single block within a Chunk. - std::size_t blockSize_; + ::std::size_t blockSize_; /// Number of blocks managed by each Chunk. unsigned char numBlocks_; @@ -248,7 +248,7 @@ ~FixedAllocator(); /// Initializes a FixedAllocator by calculating # of blocks per Chunk. - void Initialize( std::size_t blockSize, std::size_t pageSize ); + void Initialize( ::std::size_t blockSize, ::std::size_t pageSize ); /** Returns pointer to allocated memory block of fixed size - or nullptr if it failed to allocate. @@ -263,7 +263,7 @@ bool Deallocate( void * p, Chunk * hint ); /// Returns block size with which the FixedAllocator was initialized. - inline std::size_t BlockSize() const { return blockSize_; } + inline ::std::size_t BlockSize() const { return blockSize_; } /** Releases the memory used by the empty Chunk. This will take constant time under any situation. @@ -281,7 +281,7 @@ /** Returns count of empty Chunks held by this allocator. Complexity is O(C) where C is the total number of Chunks - empty or used. */ - std::size_t CountEmptyChunks( void ) const; + ::std::size_t CountEmptyChunks( void ) const; /** Determines if FixedAllocator is corrupt. Checks data members to see if any have erroneous values, or violate class invariants. It @@ -315,7 +315,7 @@ @param doThrow True if this function should throw an exception, or false if it should indicate failure by returning a nullptr pointer. */ -void * DefaultAllocator( std::size_t numBytes, bool doThrow ); +void * DefaultAllocator( ::std::size_t numBytes, bool doThrow ); /** @ingroup SmallObjectGroupInternal Calls default deallocator when SmallObjAllocator decides not to handle a @@ -329,12 +329,12 @@ // Chunk::Init ---------------------------------------------------------------- -bool Chunk::Init( std::size_t blockSize, unsigned char blocks ) +bool Chunk::Init( ::std::size_t blockSize, unsigned char blocks ) { assert(blockSize > 0); assert(blocks > 0); // Overflow check - const std::size_t allocSize = blockSize * blocks; + const ::std::size_t allocSize = blockSize * blocks; assert( allocSize / blockSize == blocks); #ifdef USE_NEW_TO_ALLOCATE @@ -345,7 +345,8 @@ // malloc can't throw, so its only way to indicate an error is to return // a nullptr pointer, so we have to check for that. pData_ = static_cast< unsigned char * >( ::std::malloc( allocSize ) ); - if ( nullptr == pData_ ) return false; + if ( nullptr == pData_ ) + return false; #endif Reset( blockSize, blocks ); @@ -354,7 +355,7 @@ // Chunk::Reset --------------------------------------------------------------- -void Chunk::Reset(std::size_t blockSize, unsigned char blocks) +void Chunk::Reset(::std::size_t blockSize, unsigned char blocks) { assert(blockSize > 0); assert(blocks > 0); @@ -385,9 +386,10 @@ // Chunk::Allocate ------------------------------------------------------------ -void* Chunk::Allocate(std::size_t blockSize) +void* Chunk::Allocate(::std::size_t blockSize) { - if ( IsFilled() ) return nullptr; + if ( IsFilled() ) + return nullptr; assert((firstAvailableBlock_ * blockSize) / blockSize == firstAvailableBlock_); @@ -400,7 +402,7 @@ // Chunk::Deallocate ---------------------------------------------------------- -void Chunk::Deallocate(void* p, std::size_t blockSize) +void Chunk::Deallocate(void* p, ::std::size_t blockSize) { assert(p >= pData_); @@ -428,7 +430,7 @@ // Chunk::IsCorrupt ----------------------------------------------------------- -bool Chunk::IsCorrupt( unsigned char numBlocks, std::size_t blockSize, +bool Chunk::IsCorrupt( unsigned char numBlocks, ::std::size_t blockSize, bool checkIndexes ) const { @@ -457,7 +459,7 @@ /* If the bit at index was set in foundBlocks, then the stealth index was found on the linked-list. */ - std::bitset< UCHAR_MAX > foundBlocks; + ::std::bitset< UCHAR_MAX > foundBlocks; unsigned char * nextBlock = nullptr; /* The loop goes along singly linked-list of stealth indexes and makes sure @@ -530,7 +532,7 @@ // Chunk::IsBlockAvailable ---------------------------------------------------- bool Chunk::IsBlockAvailable( void * p, unsigned char numBlocks, - std::size_t blockSize ) const + ::std::size_t blockSize ) const { (void) numBlocks; @@ -551,7 +553,7 @@ /* If the bit at index was set in foundBlocks, then the stealth index was found on the linked-list. */ - std::bitset< UCHAR_MAX > foundBlocks; + ::std::bitset< UCHAR_MAX > foundBlocks; unsigned char * nextBlock = nullptr; for ( unsigned char cc = 0; ; ) { @@ -597,13 +599,13 @@ // FixedAllocator::Initialize ------------------------------------------------- -void FixedAllocator::Initialize( std::size_t blockSize, std::size_t pageSize ) +void FixedAllocator::Initialize( ::std::size_t blockSize, ::std::size_t pageSize ) { assert( blockSize > 0 ); assert( pageSize >= blockSize ); blockSize_ = blockSize; - std::size_t numBlocks = pageSize / blockSize; + ::std::size_t numBlocks = pageSize / blockSize; if ( numBlocks > MaxObjectsPerChunk_ ) numBlocks = MaxObjectsPerChunk_; else if ( numBlocks < MinObjectsPerChunk_ ) numBlocks = MinObjectsPerChunk_; @@ -613,13 +615,13 @@ // FixedAllocator::CountEmptyChunks ------------------------------------------- -std::size_t FixedAllocator::CountEmptyChunks( void ) const +::std::size_t FixedAllocator::CountEmptyChunks( void ) const { #ifdef DO_EXTRA_LOKI_TESTS // This code is only used for specialized tests of the allocator. // It is #ifdef-ed so that its O(C) complexity does not overwhelm the // functions which call it. - std::size_t count = 0; + ::std::size_t count = 0; for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it ) { const Chunk & chunk = *it; @@ -639,7 +641,7 @@ const bool isEmpty = chunks_.empty(); ChunkCIter start( chunks_.begin() ); ChunkCIter last( chunks_.end() ); - const size_t emptyChunkCount = CountEmptyChunks(); + const ::std::size_t emptyChunkCount = CountEmptyChunks(); if ( isEmpty ) { @@ -751,7 +753,7 @@ const Chunk * FixedAllocator::HasBlock( void * p ) const { - const std::size_t chunkLength = numBlocks_ * blockSize_; + const ::std::size_t chunkLength = numBlocks_ * blockSize_; for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it ) { const Chunk & chunk = *it; @@ -767,7 +769,8 @@ { // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); - if ( nullptr == emptyChunk_ ) return false; + if ( nullptr == emptyChunk_ ) + return false; // If emptyChunk_ points to valid Chunk, then chunk list is not empty. assert( !chunks_.empty() ); @@ -776,7 +779,7 @@ Chunk * lastChunk = &chunks_.back(); if ( lastChunk != emptyChunk_ ) - std::swap( *emptyChunk_, *lastChunk ); + ::std::swap( *emptyChunk_, *lastChunk ); assert( lastChunk->HasAvailable( numBlocks_ ) ); lastChunk->Release(); chunks_.pop_back(); @@ -833,7 +836,7 @@ bool allocated = false; try { - std::size_t size = chunks_.size(); + ::std::size_t size = chunks_.size(); // Calling chunks_.reserve *before* creating and initializing the new // Chunk means that nothing is leaked by this function in case an // exception is thrown from reserve. @@ -954,38 +957,44 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const { - if ( chunks_.empty() ) return nullptr; + if ( chunks_.empty() ) + return nullptr; assert(deallocChunk_); - const std::size_t chunkLength = numBlocks_ * blockSize_; + const ::std::size_t chunkLength = numBlocks_ * blockSize_; Chunk * lo = deallocChunk_; Chunk * hi = deallocChunk_ + 1; const Chunk * loBound = &chunks_.front(); const Chunk * hiBound = &chunks_.back() + 1; // Special case: deallocChunk_ is the last in the array - if (hi == hiBound) hi = nullptr; + if ( hi == hiBound ) + hi = nullptr; for (;;) { if (lo) { - if ( lo->HasBlock( p, chunkLength ) ) return lo; + if ( lo->HasBlock( p, chunkLength ) ) + return lo; if ( lo == loBound ) { lo = nullptr; - if ( nullptr == hi ) break; + if ( nullptr == hi ) + break; } else --lo; } if (hi) { - if ( hi->HasBlock( p, chunkLength ) ) return hi; + if ( hi->HasBlock( p, chunkLength ) ) + return hi; if ( ++hi == hiBound ) { hi = nullptr; - if ( nullptr == lo ) break; + if ( nullptr == lo ) + break; } } } @@ -1025,7 +1034,7 @@ if ( lastChunk == deallocChunk_ ) deallocChunk_ = emptyChunk_; else if ( lastChunk != emptyChunk_ ) - std::swap( *emptyChunk_, *lastChunk ); + ::std::swap( *emptyChunk_, *lastChunk ); assert( lastChunk->HasAvailable( numBlocks_ ) ); lastChunk->Release(); chunks_.pop_back(); @@ -1042,15 +1051,15 @@ // GetOffset ------------------------------------------------------------------ /// @ingroup SmallObjectGroupInternal /// Calculates index into array where a FixedAllocator of numBytes is located. -inline std::size_t GetOffset( std::size_t numBytes, std::size_t alignment ) +inline ::std::size_t GetOffset( ::std::size_t numBytes, ::std::size_t alignment ) { - const std::size_t alignExtra = alignment-1; + const ::std::size_t alignExtra = alignment-1; return ( numBytes + alignExtra ) / alignment; } // DefaultAllocator ----------------------------------------------------------- -void * DefaultAllocator( std::size_t numBytes, bool doThrow ) +void * DefaultAllocator( ::std::size_t numBytes, bool doThrow ) { #ifdef USE_NEW_TO_ALLOCATE return doThrow ? ::operator new( numBytes ) : @@ -1083,8 +1092,8 @@ // SmallObjAllocator::SmallObjAllocator --------------------------------------- -SmallObjAllocator::SmallObjAllocator( std::size_t pageSize, - std::size_t maxObjectSize, std::size_t objectAlignSize ) : +SmallObjAllocator::SmallObjAllocator( ::std::size_t pageSize, + ::std::size_t maxObjectSize, ::std::size_t objectAlignSize ) : pool_( nullptr ), maxSmallObjectSize_( maxObjectSize ), objectAlignSize_( objectAlignSize ) @@ -1093,9 +1102,9 @@ std::cout << "SmallObjAllocator " << this << std::endl; #endif assert( 0 != objectAlignSize ); - const std::size_t allocCount = GetOffset( maxObjectSize, objectAlignSize ); + const ::std::size_t allocCount = GetOffset( maxObjectSize, objectAlignSize ); pool_ = new FixedAllocator[ allocCount ]; - for ( std::size_t i = 0; i < allocCount; ++i ) + for ( ::std::size_t i = 0; i < allocCount; ++i ) pool_[ i ].Initialize( ( i+1 ) * objectAlignSize, pageSize ); } @@ -1114,8 +1123,8 @@ bool SmallObjAllocator::TrimExcessMemory( void ) { bool found = false; - const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); - std::size_t i = 0; + const ::std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + ::std::size_t i = 0; for ( ; i < allocCount; ++i ) { if ( pool_[ i ].TrimEmptyChunk() ) @@ -1132,15 +1141,15 @@ // SmallObjAllocator::Allocate ------------------------------------------------ -void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow ) +void * SmallObjAllocator::Allocate( ::std::size_t numBytes, bool doThrow ) { if ( numBytes > GetMaxObjectSize() ) return DefaultAllocator( numBytes, doThrow ); assert( nullptr != pool_ ); if ( 0 == numBytes ) numBytes = 1; - const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; - const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + const ::std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; + const ::std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); (void) allocCount; assert( index < allocCount ); @@ -1167,9 +1176,10 @@ // SmallObjAllocator::Deallocate ---------------------------------------------- -void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes ) +void SmallObjAllocator::Deallocate( void * p, ::std::size_t numBytes ) { - if ( nullptr == p ) return; + if ( nullptr == p ) + return; if ( numBytes > GetMaxObjectSize() ) { DefaultDeallocator( p ); @@ -1177,8 +1187,8 @@ } assert( nullptr != pool_ ); if ( 0 == numBytes ) numBytes = 1; - const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; - const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + const ::std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; + const ::std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); (void) allocCount; assert( index < allocCount ); FixedAllocator & allocator = pool_[ index ]; @@ -1193,13 +1203,14 @@ void SmallObjAllocator::Deallocate( void * p ) { - if ( nullptr == p ) return; + if ( nullptr == p ) + return; assert( nullptr != pool_ ); - ::Loki::Private::FixedAllocator * pAllocator = nullptr; - const std::size_t allocCount = ::Loki::Private::GetOffset( GetMaxObjectSize(), GetAlignment() ); + FixedAllocator * pAllocator = nullptr; + const ::std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); Chunk * chunk = nullptr; - for ( std::size_t ii = 0; ii < allocCount; ++ii ) + for ( ::std::size_t ii = 0; ii < allocCount; ++ii ) { chunk = pool_[ ii ].HasBlock( p ); if ( nullptr != chunk ) @@ -1239,8 +1250,8 @@ assert( false ); return true; } - const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); - for ( std::size_t ii = 0; ii < allocCount; ++ii ) + const ::std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + for ( ::std::size_t ii = 0; ii < allocCount; ++ii ) { if ( pool_[ ii ].IsCorrupt() ) return true; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-08 01:03:27
|
Revision: 1071 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1071&view=rev Author: rich_sposato Date: 2010-09-08 01:03:21 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Put some code within Loki::Private namespace. Modified Paths: -------------- trunk/include/loki/SmallObj.h trunk/src/SmallObj.cpp Modified: trunk/include/loki/SmallObj.h =================================================================== --- trunk/include/loki/SmallObj.h 2010-09-08 00:48:29 UTC (rev 1070) +++ trunk/include/loki/SmallObj.h 2010-09-08 01:03:21 UTC (rev 1071) @@ -75,7 +75,10 @@ } - class FixedAllocator; + namespace Private + { + class FixedAllocator; + }; // end namespace Private /** @class SmallObjAllocator @ingroup SmallObjectGroupInternal @@ -92,8 +95,8 @@ @param maxObjectSize Max # of bytes which this may allocate. @param objectAlignSize # of bytes between alignment boundaries. */ - SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize, - std::size_t objectAlignSize ); + SmallObjAllocator( ::std::size_t pageSize, ::std::size_t maxObjectSize, + ::std::size_t objectAlignSize ); /** Destructor releases all blocks, all Chunks, and FixedAllocator's. Any outstanding blocks are unavailable, and should not be used after @@ -150,7 +153,7 @@ void Deallocate( void * p ); /// Returns max # of bytes which this can allocate. - inline std::size_t GetMaxObjectSize() const + inline ::std::size_t GetMaxObjectSize() const { return maxSmallObjectSize_; } /// Returns # of bytes between allocation boundaries. @@ -184,16 +187,15 @@ SmallObjAllocator & operator = ( const SmallObjAllocator & ); /// Pointer to array of fixed-size allocators. - Loki::FixedAllocator * pool_; + ::Loki::Private::FixedAllocator * pool_; /// Largest object size supported by allocators. - const std::size_t maxSmallObjectSize_; + const ::std::size_t maxSmallObjectSize_; /// Size of alignment boundaries. - const std::size_t objectAlignSize_; + const ::std::size_t objectAlignSize_; }; - /** @class AllocatorSingleton @ingroup SmallObjectGroupInternal This template class is derived from Modified: trunk/src/SmallObj.cpp =================================================================== --- trunk/src/SmallObj.cpp 2010-09-08 00:48:29 UTC (rev 1070) +++ trunk/src/SmallObj.cpp 2010-09-08 01:03:21 UTC (rev 1071) @@ -15,6 +15,7 @@ // $Id$ +// ---------------------------------------------------------------------------- #include <loki/SmallObj.h> @@ -32,13 +33,17 @@ #endif #if !defined( nullptr ) - #define nullptr + #define nullptr 0 #endif namespace Loki { +namespace Private +{ +// ---------------------------------------------------------------------------- + /** @struct Chunk @ingroup SmallObjectGroupInternal Contains info about each allocated Chunk - which is a collection of @@ -302,6 +307,26 @@ unsigned char FixedAllocator::MinObjectsPerChunk_ = 8; unsigned char FixedAllocator::MaxObjectsPerChunk_ = UCHAR_MAX; +/** @ingroup SmallObjectGroupInternal + Calls the default allocator when SmallObjAllocator decides not to handle a + request. SmallObjAllocator calls this if the number of bytes is bigger than + the size which can be handled by any FixedAllocator. + @param numBytes number of bytes + @param doThrow True if this function should throw an exception, or false if it + should indicate failure by returning a nullptr pointer. +*/ +void * DefaultAllocator( std::size_t numBytes, bool doThrow ); + +/** @ingroup SmallObjectGroupInternal + Calls default deallocator when SmallObjAllocator decides not to handle a + request. The default deallocator could be the global delete operator or the + free function. The free function is the preferred default deallocator since + it matches malloc which is the preferred default allocator. SmallObjAllocator + will call this if an address was not found among any of its own blocks. + */ +void DefaultDeallocator( void * p ); + + // Chunk::Init ---------------------------------------------------------------- bool Chunk::Init( std::size_t blockSize, unsigned char blocks ) @@ -1024,14 +1049,7 @@ } // DefaultAllocator ----------------------------------------------------------- -/** @ingroup SmallObjectGroupInternal - Calls the default allocator when SmallObjAllocator decides not to handle a - request. SmallObjAllocator calls this if the number of bytes is bigger than - the size which can be handled by any FixedAllocator. - @param numBytes number of bytes - @param doThrow True if this function should throw an exception, or false if it - should indicate failure by returning a nullptr pointer. -*/ + void * DefaultAllocator( std::size_t numBytes, bool doThrow ) { #ifdef USE_NEW_TO_ALLOCATE @@ -1046,13 +1064,7 @@ } // DefaultDeallocator --------------------------------------------------------- -/** @ingroup SmallObjectGroupInternal - Calls default deallocator when SmallObjAllocator decides not to handle a - request. The default deallocator could be the global delete operator or the - free function. The free function is the preferred default deallocator since - it matches malloc which is the preferred default allocator. SmallObjAllocator - will call this if an address was not found among any of its own blocks. - */ + void DefaultDeallocator( void * p ) { #ifdef USE_NEW_TO_ALLOCATE @@ -1062,6 +1074,13 @@ #endif } +// ---------------------------------------------------------------------------- + +}; // end namespace Private + +using namespace ::Loki::Private; + + // SmallObjAllocator::SmallObjAllocator --------------------------------------- SmallObjAllocator::SmallObjAllocator( std::size_t pageSize, @@ -1176,8 +1195,8 @@ { if ( nullptr == p ) return; assert( nullptr != pool_ ); - FixedAllocator * pAllocator = nullptr; - const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + ::Loki::Private::FixedAllocator * pAllocator = nullptr; + const std::size_t allocCount = ::Loki::Private::GetOffset( GetMaxObjectSize(), GetAlignment() ); Chunk * chunk = nullptr; for ( std::size_t ii = 0; ii < allocCount; ++ii ) @@ -1230,4 +1249,3 @@ } } // end namespace Loki - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-09-08 00:48:35
|
Revision: 1070 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1070&view=rev Author: rich_sposato Date: 2010-09-08 00:48:29 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Replaced NULL with nullptr. Modified Paths: -------------- trunk/src/SmallObj.cpp Modified: trunk/src/SmallObj.cpp =================================================================== --- trunk/src/SmallObj.cpp 2010-04-19 03:09:59 UTC (rev 1069) +++ trunk/src/SmallObj.cpp 2010-09-08 00:48:29 UTC (rev 1070) @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// @@ -31,6 +31,11 @@ #include <iostream> #endif +#if !defined( nullptr ) + #define nullptr +#endif + + namespace Loki { @@ -157,12 +162,12 @@ @par Class Level Invariants - There is always either zero or one Chunk which is empty. - - If this has no empty Chunk, then emptyChunk_ is NULL. + - If this has no empty Chunk, then emptyChunk_ is nullptr. - If this has an empty Chunk, then emptyChunk_ points to it. - If the Chunk container is empty, then deallocChunk_ and allocChunk_ - are NULL. + are nullptr. - If the Chunk container is not-empty, then deallocChunk_ and allocChunk_ - are either NULL or point to Chunks within the container. + are either nullptr or point to Chunks within the container. - allocChunk_ will often point to the last Chunk in the container since it was likely allocated most recently, and therefore likely to have an available block. @@ -194,7 +199,7 @@ were allocated. Opposite order = objects are deallocated in a last to first order. Complexity is O(C) where C is count of all Chunks. This never throws. - @return Pointer to Chunk that owns p, or NULL if no owner found. + @return Pointer to Chunk that owns p, or nullptr if no owner found. */ Chunk * VicinityFind( void * p ) const; @@ -227,7 +232,7 @@ Chunk * allocChunk_; /// Pointer to Chunk used for last or next deallocation. Chunk * deallocChunk_; - /// Pointer to the only empty Chunk if there is one, else NULL. + /// Pointer to the only empty Chunk if there is one, else nullptr. Chunk * emptyChunk_; public: @@ -240,7 +245,7 @@ /// Initializes a FixedAllocator by calculating # of blocks per Chunk. void Initialize( std::size_t blockSize, std::size_t pageSize ); - /** Returns pointer to allocated memory block of fixed size - or NULL + /** Returns pointer to allocated memory block of fixed size - or nullptr if it failed to allocate. */ void * Allocate( void ); @@ -313,9 +318,9 @@ pData_ = static_cast< unsigned char * >( ::operator new ( allocSize ) ); #else // malloc can't throw, so its only way to indicate an error is to return - // a NULL pointer, so we have to check for that. + // a nullptr pointer, so we have to check for that. pData_ = static_cast< unsigned char * >( ::std::malloc( allocSize ) ); - if ( NULL == pData_ ) return false; + if ( nullptr == pData_ ) return false; #endif Reset( blockSize, blocks ); @@ -345,7 +350,7 @@ void Chunk::Release() { - assert( NULL != pData_ ); + assert( nullptr != pData_ ); #ifdef USE_NEW_TO_ALLOCATE ::operator delete ( pData_ ); #else @@ -357,9 +362,9 @@ void* Chunk::Allocate(std::size_t blockSize) { - if ( IsFilled() ) return NULL; + if ( IsFilled() ) return nullptr; - assert((firstAvailableBlock_ * blockSize) / blockSize == + assert((firstAvailableBlock_ * blockSize) / blockSize == firstAvailableBlock_); unsigned char * pResult = pData_ + (firstAvailableBlock_ * blockSize); firstAvailableBlock_ = *pResult; @@ -428,7 +433,7 @@ found on the linked-list. */ std::bitset< UCHAR_MAX > foundBlocks; - unsigned char * nextBlock = NULL; + unsigned char * nextBlock = nullptr; /* The loop goes along singly linked-list of stealth indexes and makes sure that each index is within bounds (0 <= index < numBlocks) and that the @@ -503,7 +508,7 @@ std::size_t blockSize ) const { (void) numBlocks; - + if ( IsFilled() ) return false; @@ -522,7 +527,7 @@ found on the linked-list. */ std::bitset< UCHAR_MAX > foundBlocks; - unsigned char * nextBlock = NULL; + unsigned char * nextBlock = nullptr; for ( unsigned char cc = 0; ; ) { nextBlock = pData_ + ( index * blockSize ); @@ -547,9 +552,9 @@ : blockSize_( 0 ) , numBlocks_( 0 ) , chunks_( 0 ) - , allocChunk_( NULL ) - , deallocChunk_( NULL ) - , emptyChunk_( NULL ) + , allocChunk_( nullptr ) + , deallocChunk_( nullptr ) + , emptyChunk_( nullptr ) { } @@ -598,7 +603,7 @@ } return count; #else - return ( NULL == emptyChunk_ ) ? 0 : 1; + return ( nullptr == emptyChunk_ ) ? 0 : 1; #endif } @@ -623,17 +628,17 @@ assert( false ); return true; } - if ( NULL != deallocChunk_ ) + if ( nullptr != deallocChunk_ ) { assert( false ); return true; } - if ( NULL != allocChunk_ ) + if ( nullptr != allocChunk_ ) { assert( false ); return true; } - if ( NULL != emptyChunk_ ) + if ( nullptr != emptyChunk_ ) { assert( false ); return true; @@ -673,14 +678,14 @@ switch ( emptyChunkCount ) { case 0: - if ( emptyChunk_ != NULL ) + if ( emptyChunk_ != nullptr ) { assert( false ); return true; } break; case 1: - if ( emptyChunk_ == NULL ) + if ( emptyChunk_ == nullptr ) { assert( false ); return true; @@ -728,7 +733,7 @@ if ( chunk.HasBlock( p, chunkLength ) ) return &chunk; } - return NULL; + return nullptr; } // FixedAllocator::TrimEmptyChunk --------------------------------------------- @@ -736,8 +741,8 @@ bool FixedAllocator::TrimEmptyChunk( void ) { // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. - assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); - if ( NULL == emptyChunk_ ) return false; + assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + if ( nullptr == emptyChunk_ ) return false; // If emptyChunk_ points to valid Chunk, then chunk list is not empty. assert( !chunks_.empty() ); @@ -753,8 +758,8 @@ if ( chunks_.empty() ) { - allocChunk_ = NULL; - deallocChunk_ = NULL; + allocChunk_ = nullptr; + deallocChunk_ = nullptr; } else { @@ -770,7 +775,7 @@ } } - emptyChunk_ = NULL; + emptyChunk_ = nullptr; assert( 0 == CountEmptyChunks() ); return true; @@ -782,8 +787,8 @@ { if ( chunks_.empty() ) { - assert( NULL == allocChunk_ ); - assert( NULL == deallocChunk_ ); + assert( nullptr == allocChunk_ ); + assert( nullptr == deallocChunk_ ); } if ( chunks_.size() == chunks_.capacity() ) @@ -833,15 +838,15 @@ void * FixedAllocator::Allocate( void ) { // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. - assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); assert( CountEmptyChunks() < 2 ); - if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() ) + if ( ( nullptr == allocChunk_ ) || allocChunk_->IsFilled() ) { - if ( NULL != emptyChunk_ ) + if ( nullptr != emptyChunk_ ) { allocChunk_ = emptyChunk_; - emptyChunk_ = NULL; + emptyChunk_ = nullptr; } else { @@ -850,7 +855,7 @@ if ( chunks_.end() == i ) { if ( !MakeNewChunk() ) - return NULL; + return nullptr; break; } if ( !i->IsFilled() ) @@ -862,23 +867,23 @@ } } else if ( allocChunk_ == emptyChunk_) - // detach emptyChunk_ from allocChunk_, because after - // calling allocChunk_->Allocate(blockSize_); the chunk + // detach emptyChunk_ from allocChunk_, because after + // calling allocChunk_->Allocate(blockSize_); the chunk // is no longer empty. - emptyChunk_ = NULL; + emptyChunk_ = nullptr; - assert( allocChunk_ != NULL ); + assert( allocChunk_ != nullptr ); assert( !allocChunk_->IsFilled() ); void * place = allocChunk_->Allocate( blockSize_ ); // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. - assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); assert( CountEmptyChunks() < 2 ); #ifdef LOKI_CHECK_FOR_CORRUPTION if ( allocChunk_->IsCorrupt( numBlocks_, blockSize_, true ) ) { assert( false ); - return NULL; + return nullptr; } #endif @@ -896,8 +901,8 @@ assert( &chunks_.back() >= allocChunk_ ); assert( CountEmptyChunks() < 2 ); - Chunk * foundChunk = ( NULL == hint ) ? VicinityFind( p ) : hint; - if ( NULL == foundChunk ) + Chunk * foundChunk = ( nullptr == hint ) ? VicinityFind( p ) : hint; + if ( nullptr == foundChunk ) return false; assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) ); @@ -924,7 +929,7 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const { - if ( chunks_.empty() ) return NULL; + if ( chunks_.empty() ) return nullptr; assert(deallocChunk_); const std::size_t chunkLength = numBlocks_ * blockSize_; @@ -934,7 +939,7 @@ const Chunk * hiBound = &chunks_.back() + 1; // Special case: deallocChunk_ is the last in the array - if (hi == hiBound) hi = NULL; + if (hi == hiBound) hi = nullptr; for (;;) { @@ -943,8 +948,8 @@ if ( lo->HasBlock( p, chunkLength ) ) return lo; if ( lo == loBound ) { - lo = NULL; - if ( NULL == hi ) break; + lo = nullptr; + if ( nullptr == hi ) break; } else --lo; } @@ -954,13 +959,13 @@ if ( hi->HasBlock( p, chunkLength ) ) return hi; if ( ++hi == hiBound ) { - hi = NULL; - if ( NULL == lo ) break; + hi = nullptr; + if ( nullptr == lo ) break; } } } - return NULL; + return nullptr; } // FixedAllocator::DoDeallocate ----------------------------------------------- @@ -974,7 +979,7 @@ assert( emptyChunk_ != deallocChunk_ ); assert( !deallocChunk_->HasAvailable( numBlocks_ ) ); // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. - assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); // call into the chunk, will adjust the inner list but won't release memory deallocChunk_->Deallocate(p, blockSize_); @@ -986,7 +991,7 @@ // empty chunks. Since emptyChunk_ may only point to a previously // cleared Chunk, if it points to something else besides deallocChunk_, // then FixedAllocator currently has 2 empty Chunks. - if ( NULL != emptyChunk_ ) + if ( nullptr != emptyChunk_ ) { // If last Chunk is empty, just change what deallocChunk_ // points to, and release the last. Otherwise, swap an empty @@ -999,14 +1004,14 @@ assert( lastChunk->HasAvailable( numBlocks_ ) ); lastChunk->Release(); chunks_.pop_back(); - if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() ) + if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() ) allocChunk_ = deallocChunk_; } emptyChunk_ = deallocChunk_; } // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. - assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); } // GetOffset ------------------------------------------------------------------ @@ -1025,7 +1030,7 @@ the size which can be handled by any FixedAllocator. @param numBytes number of bytes @param doThrow True if this function should throw an exception, or false if it - should indicate failure by returning a NULL pointer. + should indicate failure by returning a nullptr pointer. */ void * DefaultAllocator( std::size_t numBytes, bool doThrow ) { @@ -1034,7 +1039,7 @@ ::operator new( numBytes, std::nothrow_t() ); #else void * p = ::std::malloc( numBytes ); - if ( doThrow && ( NULL == p ) ) + if ( doThrow && ( nullptr == p ) ) throw std::bad_alloc(); return p; #endif @@ -1042,7 +1047,7 @@ // DefaultDeallocator --------------------------------------------------------- /** @ingroup SmallObjectGroupInternal - Calls default deallocator when SmallObjAllocator decides not to handle a + Calls default deallocator when SmallObjAllocator decides not to handle a request. The default deallocator could be the global delete operator or the free function. The free function is the preferred default deallocator since it matches malloc which is the preferred default allocator. SmallObjAllocator @@ -1061,7 +1066,7 @@ SmallObjAllocator::SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize, std::size_t objectAlignSize ) : - pool_( NULL ), + pool_( nullptr ), maxSmallObjectSize_( maxObjectSize ), objectAlignSize_( objectAlignSize ) { @@ -1113,7 +1118,7 @@ if ( numBytes > GetMaxObjectSize() ) return DefaultAllocator( numBytes, doThrow ); - assert( NULL != pool_ ); + assert( nullptr != pool_ ); if ( 0 == numBytes ) numBytes = 1; const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); @@ -1125,10 +1130,10 @@ assert( allocator.BlockSize() < numBytes + GetAlignment() ); void * place = allocator.Allocate(); - if ( ( NULL == place ) && TrimExcessMemory() ) + if ( ( nullptr == place ) && TrimExcessMemory() ) place = allocator.Allocate(); - if ( ( NULL == place ) && doThrow ) + if ( ( nullptr == place ) && doThrow ) { #ifdef _MSC_VER throw std::bad_alloc( "could not allocate small object" ); @@ -1145,13 +1150,13 @@ void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes ) { - if ( NULL == p ) return; + if ( nullptr == p ) return; if ( numBytes > GetMaxObjectSize() ) { DefaultDeallocator( p ); return; } - assert( NULL != pool_ ); + assert( nullptr != pool_ ); if ( 0 == numBytes ) numBytes = 1; const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); @@ -1160,7 +1165,7 @@ FixedAllocator & allocator = pool_[ index ]; assert( allocator.BlockSize() >= numBytes ); assert( allocator.BlockSize() < numBytes + GetAlignment() ); - const bool found = allocator.Deallocate( p, NULL ); + const bool found = allocator.Deallocate( p, nullptr ); (void) found; assert( found ); } @@ -1169,28 +1174,28 @@ void SmallObjAllocator::Deallocate( void * p ) { - if ( NULL == p ) return; - assert( NULL != pool_ ); - FixedAllocator * pAllocator = NULL; + if ( nullptr == p ) return; + assert( nullptr != pool_ ); + FixedAllocator * pAllocator = nullptr; const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); - Chunk * chunk = NULL; + Chunk * chunk = nullptr; for ( std::size_t ii = 0; ii < allocCount; ++ii ) { chunk = pool_[ ii ].HasBlock( p ); - if ( NULL != chunk ) + if ( nullptr != chunk ) { pAllocator = &pool_[ ii ]; break; } } - if ( NULL == pAllocator ) + if ( nullptr == pAllocator ) { DefaultDeallocator( p ); return; } - assert( NULL != chunk ); + assert( nullptr != chunk ); const bool found = pAllocator->Deallocate( p, chunk ); (void) found; assert( found ); @@ -1200,7 +1205,7 @@ bool SmallObjAllocator::IsCorrupt( void ) const { - if ( NULL == pool_ ) + if ( nullptr == pool_ ) { assert( false ); return true; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2010-04-19 03:10:06
|
Revision: 1069 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1069&view=rev Author: rich_sposato Date: 2010-04-19 03:09:59 +0000 (Mon, 19 Apr 2010) Log Message: ----------- Loki header files now all have consistent include statement style. Modified Paths: -------------- trunk/include/loki/AbstractFactory.h trunk/include/loki/DataGenerators.h trunk/include/loki/Factory.h trunk/include/loki/Functor.h trunk/include/loki/HierarchyGenerators.h trunk/include/loki/LokiTypeInfo.h trunk/include/loki/MultiMethods.h trunk/include/loki/OrderedStatic.h trunk/include/loki/Register.h trunk/include/loki/Sequence.h trunk/include/loki/Singleton.h trunk/include/loki/SmallObj.h trunk/include/loki/SmartPtr.h trunk/include/loki/TypeTraits.h trunk/include/loki/Typelist.h trunk/include/loki/Visitor.h Modified: trunk/include/loki/AbstractFactory.h =================================================================== --- trunk/include/loki/AbstractFactory.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/AbstractFactory.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_ABSTRACTFACTORY_INC_ @@ -18,10 +18,10 @@ // $Id$ -#include "Typelist.h" -#include "Sequence.h" -#include "TypeManip.h" -#include "HierarchyGenerators.h" +#include <loki/Typelist.h> +#include <loki/Sequence.h> +#include <loki/TypeManip.h> +#include <loki/HierarchyGenerators.h> #include <cassert> @@ -31,7 +31,7 @@ * \ingroup FactoriesGroup * \brief Implements an abstract object factory. */ - + /** * \class AbstractFactory * \ingroup AbstractFactoryGroup @@ -68,14 +68,14 @@ { public: typedef TList ProductList; - + template <class T> T* Create() { Unit<T>& unit = *this; return unit.DoCreate(Type2Type<T>()); } }; - + //////////////////////////////////////////////////////////////////////////////// // class template OpNewFactoryUnit // Creates an object by invoking the new operator @@ -85,10 +85,10 @@ class OpNewFactoryUnit : public Base { typedef typename Base::ProductList BaseProductList; - + protected: typedef typename BaseProductList::Tail ProductList; - + public: typedef typename BaseProductList::Head AbstractProduct; ConcreteProduct* DoCreate(Type2Type<AbstractProduct>) @@ -101,7 +101,7 @@ // class template PrototypeFactoryUnit // Creates an object by cloning a prototype // There is a difference between the implementation herein and the one described -// in the book: GetPrototype and SetPrototype use the helper friend +// in the book: GetPrototype and SetPrototype use the helper friend // functions DoGetPrototype and DoSetPrototype. The friend functions avoid // name hiding issues. Plus, GetPrototype takes a reference to pointer // instead of returning the pointer by value. @@ -111,7 +111,7 @@ class PrototypeFactoryUnit : public Base { typedef typename Base::ProductList BaseProductList; - + protected: typedef typename BaseProductList::Tail ProductList; @@ -133,17 +133,17 @@ template <class U> void GetPrototype(U*& p) { return DoGetPrototype(*this, p); } - + template <class U> void SetPrototype(U* pObj) { DoSetPrototype(*this, pObj); } - + AbstractProduct* DoCreate(Type2Type<AbstractProduct>) { assert(pPrototype_); return pPrototype_->Clone(); } - + private: AbstractProduct* pPrototype_; }; Modified: trunk/include/loki/DataGenerators.h =================================================================== --- trunk/include/loki/DataGenerators.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/DataGenerators.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -2,7 +2,7 @@ // The Loki Library // Data Generator by Shannon Barber // This code DOES NOT accompany the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. // // Code covered by the MIT License @@ -15,7 +15,7 @@ // $Id$ -#include "Typelist.h" +#include <loki/Typelist.h> //Reference version @@ -64,7 +64,7 @@ }; template <class TList, template <class> class GenFunc> struct IterateTypes; - + template <class T1, class T2, template <class> class GenFunc> struct IterateTypes<Typelist<T1, T2>, GenFunc> { @@ -79,7 +79,7 @@ tail.operator()(ii); } }; - + template <class AtomicType, template <class> class GenFunc> struct IterateTypes { @@ -91,7 +91,7 @@ ++ii; //Is this even needed? } }; - + template <template <class> class GenFunc> struct IterateTypes<NullType, GenFunc> { @@ -99,7 +99,7 @@ void operator()(II ii) {} }; - + template<typename Types, template <class> class UnitFunc, typename II> void iterate_types(II ii) { Modified: trunk/include/loki/Factory.h =================================================================== --- trunk/include/loki/Factory.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/Factory.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -16,11 +16,11 @@ // $Id$ -#include "LokiTypeInfo.h" -#include "Functor.h" -#include "AssocVector.h" -#include "SmallObj.h" -#include "Sequence.h" +#include <loki/LokiTypeInfo.h> +#include <loki/Functor.h> +#include <loki/AssocVector.h> +#include <loki/SmallObj.h> +#include <loki/Sequence.h> #ifdef _MSC_VER #pragma warning(push) @@ -33,7 +33,7 @@ * \defgroup FactoryGroup Factory * \ingroup FactoriesGroup * \brief Implements a generic object factory. - * + * * <i>The Factory Method pattern is an object-oriented design pattern. * Like other creational patterns, it deals with the problem of creating objects * (products) without specifying the exact class of object that will be created. @@ -46,7 +46,7 @@ * whose main purpose is creation of objects.</i> * <div ALIGN="RIGHT"><a href="http://en.wikipedia.org/wiki/Factory_method_pattern"> * Wikipedia</a></div> - * + * * Loki proposes a generic version of the Factory. Here is a typical use.<br> * <code><br> * 1. Factory< AbstractProduct, int > aFactory;<br> @@ -62,7 +62,7 @@ * ProductCreator by registering them into the Factory.<br> * A ProductCreator is a just a function that will return the right object. ie <br> * <code> - * Product* createProductNull()<br> + * Product* createProductNull()<br> * {<br> * return new Product<br> * }<br> @@ -80,11 +80,11 @@ * \defgroup FactoryErrorPoliciesGroup Factory Error Policies * \ingroup FactoryGroup * \brief Manages the "Unknown Type" error in an object factory - * + * * \class DefaultFactoryError * \ingroup FactoryErrorPoliciesGroup - * \brief Default policy that throws an exception - * + * \brief Default policy that throws an exception + * */ template <typename IdentifierType, class AbstractProduct> @@ -1065,9 +1065,9 @@ return NULL; } - typename IdToProductMap::iterator i = + typename IdToProductMap::iterator i = associations_.find(typeid(*model)); - + if (i != associations_.end()) { return (i->second)(model); @@ -1079,7 +1079,7 @@ typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap; IdToProductMap associations_; }; - + } // namespace Loki Modified: trunk/include/loki/Functor.h =================================================================== --- trunk/include/loki/Functor.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/Functor.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -18,11 +18,11 @@ // $Id$ -#include "Typelist.h" -#include "Sequence.h" -#include "EmptyType.h" -#include "SmallObj.h" -#include "TypeTraits.h" +#include <loki/Typelist.h> +#include <loki/Sequence.h> +#include <loki/EmptyType.h> +#include <loki/SmallObj.h> +#include <loki/TypeTraits.h> #include <typeinfo> #include <memory> Modified: trunk/include/loki/HierarchyGenerators.h =================================================================== --- trunk/include/loki/HierarchyGenerators.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/HierarchyGenerators.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_HIERARCHYGENERATORS_INC_ @@ -18,14 +18,14 @@ // $Id$ -#include "Typelist.h" -#include "TypeTraits.h" -#include "EmptyType.h" +#include <loki/Typelist.h> +#include <loki/TypeTraits.h> +#include <loki/EmptyType.h> namespace Loki { #if defined(_MSC_VER) && _MSC_VER >= 1300 -#pragma warning( push ) +#pragma warning( push ) // 'class1' : base-class 'class2' is already a base-class of 'class3' #pragma warning( disable : 4584 ) #endif // _MSC_VER @@ -35,27 +35,27 @@ // Generates a scattered hierarchy starting from a typelist and a template // Invocation (TList is a typelist, Unit is a template of one arg): // GenScatterHierarchy<TList, Unit> -// The generated class inherits all classes generated by instantiating the -// template 'Unit' with the types contained in TList +// The generated class inherits all classes generated by instantiating the +// template 'Unit' with the types contained in TList //////////////////////////////////////////////////////////////////////////////// namespace Private { - // The following type helps to overcome subtle flaw in the original - // implementation of GenScatterHierarchy. - // The flaw is revealed when the input type list of GenScatterHierarchy - // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)). - // In this case GenScatterHierarchy will contain multiple bases of the same + // The following type helps to overcome subtle flaw in the original + // implementation of GenScatterHierarchy. + // The flaw is revealed when the input type list of GenScatterHierarchy + // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)). + // In this case GenScatterHierarchy will contain multiple bases of the same // type and some of them will not be reachable (per 10.3). // For example before the fix the first element of Tuple<LOKI_TYPELIST_2(int, int)> // is not reachable in any way! - template<class, class> + template<class, class> struct ScatterHierarchyTag; } template <class TList, template <class> class Unit> class GenScatterHierarchy; - + template <class T1, class T2, template <class> class Unit> class GenScatterHierarchy<Typelist<T1, T2>, Unit> : public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> @@ -71,10 +71,10 @@ typedef Unit<T> Result; }; }; - + // In the middle *unique* class that resolve possible ambiguity template <class T1, class T2, template <class> class Unit> - class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> + class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> : public GenScatterHierarchy<T1, Unit> { }; @@ -88,7 +88,7 @@ typedef Unit<T> Result; }; }; - + template <template <class> class Unit> class GenScatterHierarchy<NullType, Unit> { @@ -97,14 +97,14 @@ typedef Unit<T> Result; }; }; - + //////////////////////////////////////////////////////////////////////////////// // function template Field // Accesses a field in an object of a type generated with GenScatterHierarchy // Invocation (obj is an object of a type H generated with GenScatterHierarchy, // T is a type in the typelist used to generate H): // Field<T>(obj) -// returns a reference to Unit<T>, where Unit is the template used to generate H +// returns a reference to Unit<T>, where Unit is the template used to generate H //////////////////////////////////////////////////////////////////////////////// template <class T, class H> @@ -112,16 +112,16 @@ { return obj; } - + template <class T, class H> const typename H::template Rebind<T>::Result& Field(const H& obj) { return obj; } - + //////////////////////////////////////////////////////////////////////////////// // function template TupleUnit -// The building block of tuples +// The building block of tuples //////////////////////////////////////////////////////////////////////////////// template <class T> @@ -134,8 +134,8 @@ //////////////////////////////////////////////////////////////////////////////// // class template Tuple -// Implements a tuple class that holds a number of values and provides field -// access to them via the Field function (below) +// Implements a tuple class that holds a number of values and provides field +// access to them via the Field function (below) //////////////////////////////////////////////////////////////////////////////// template <class TList> @@ -149,13 +149,13 @@ //////////////////////////////////////////////////////////////////////////////// template <class H, unsigned int i> struct FieldHelper; - + template <class H> struct FieldHelper<H, 0> { typedef typename H::TList::Head ElementType; typedef typename H::template Rebind<ElementType>::Result UnitType; - + enum { isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, @@ -163,16 +163,16 @@ }; typedef const typename H::LeftBase ConstLeftBase; - - typedef typename Select<isConst, ConstLeftBase, + + typedef typename Select<isConst, ConstLeftBase, typename H::LeftBase>::Result LeftBase; - - typedef typename Select<isTuple, ElementType, + + typedef typename Select<isTuple, ElementType, UnitType>::Result UnqualifiedResultType; typedef typename Select<isConst, const UnqualifiedResultType, UnqualifiedResultType>::Result ResultType; - + static ResultType& Do(H& obj) { LeftBase& leftBase = obj; @@ -185,7 +185,7 @@ { typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType; typedef typename H::template Rebind<ElementType>::Result UnitType; - + enum { isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, @@ -193,16 +193,16 @@ }; typedef const typename H::RightBase ConstRightBase; - - typedef typename Select<isConst, ConstRightBase, + + typedef typename Select<isConst, ConstRightBase, typename H::RightBase>::Result RightBase; - typedef typename Select<isTuple, ElementType, + typedef typename Select<isTuple, ElementType, UnitType>::Result UnqualifiedResultType; typedef typename Select<isConst, const UnqualifiedResultType, UnqualifiedResultType>::Result ResultType; - + static ResultType& Do(H& obj) { RightBase& rightBase = obj; @@ -217,7 +217,7 @@ // i is the index of a type in the typelist used to generate H): // Field<i>(obj) // returns a reference to Unit<T>, where Unit is the template used to generate H -// and T is the i-th type in the typelist +// and T is the i-th type in the typelist //////////////////////////////////////////////////////////////////////////////// template <int i, class H> @@ -226,14 +226,14 @@ { return FieldHelper<H, i>::Do(obj); } - + // template <int i, class H> // const typename FieldHelper<H, i>::ResultType& // Field(const H& obj) // { // return FieldHelper<H, i>::Do(obj); // } - + //////////////////////////////////////////////////////////////////////////////// // class template GenLinearHierarchy // Generates a linear hierarchy starting from a typelist and a template @@ -248,7 +248,7 @@ class Root = EmptyType > class GenLinearHierarchy; - + template < class T1, @@ -283,7 +283,7 @@ }; #if defined(_MSC_VER) && _MSC_VER >= 1300 -#pragma warning( pop ) +#pragma warning( pop ) #endif } // namespace Loki Modified: trunk/include/loki/LokiTypeInfo.h =================================================================== --- trunk/include/loki/LokiTypeInfo.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/LokiTypeInfo.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_LOKITYPEINFO_INC_ @@ -20,7 +20,7 @@ #include <typeinfo> #include <cassert> -#include "Typelist.h" +#include <loki/Typelist.h> namespace Loki { @@ -45,24 +45,24 @@ private: const std::type_info* pInfo_; }; - + // Implementation - + inline TypeInfo::TypeInfo() { class Nil {}; pInfo_ = &typeid(Nil); assert(pInfo_); } - + inline TypeInfo::TypeInfo(const std::type_info& ti) : pInfo_(&ti) { assert(pInfo_); } - + inline bool TypeInfo::before(const TypeInfo& rhs) const { assert(pInfo_); - // type_info::before return type is int in some VC libraries + // type_info::before return type is int in some VC libraries return pInfo_->before(*rhs.pInfo_) != 0; } @@ -71,7 +71,7 @@ assert(pInfo_); return *pInfo_; } - + inline const char* TypeInfo::name() const { assert(pInfo_); @@ -79,7 +79,7 @@ } // Comparison operators - + inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs) // type_info::operator== return type is int in some VC libraries { return (lhs.Get() == rhs.Get()) != 0; } @@ -88,14 +88,14 @@ { return lhs.before(rhs); } inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs) - { return !(lhs == rhs); } - + { return !(lhs == rhs); } + inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs) { return rhs < lhs; } - + inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs) { return !(lhs > rhs); } - + inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs) { return !(lhs < rhs); } } Modified: trunk/include/loki/MultiMethods.h =================================================================== --- trunk/include/loki/MultiMethods.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/MultiMethods.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -18,10 +18,10 @@ // $Id$ -#include "Typelist.h" -#include "LokiTypeInfo.h" -#include "Functor.h" -#include "AssocVector.h" +#include <loki/Typelist.h> +#include <loki/LokiTypeInfo.h> +#include <loki/Functor.h> +#include <loki/AssocVector.h> //////////////////////////////////////////////////////////////////////////////// // IMPORTANT NOTE: Modified: trunk/include/loki/OrderedStatic.h =================================================================== --- trunk/include/loki/OrderedStatic.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/OrderedStatic.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2005 Peter K\xFCmmel -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_ORDEREDSTATIC_INC_ @@ -18,10 +18,10 @@ #include <vector> #include <iostream> -#include "LokiExport.h" -#include "Singleton.h" -#include "Typelist.h" -#include "Sequence.h" +#include <loki/LokiExport.h> +#include <loki/Singleton.h> +#include <loki/Typelist.h> +#include <loki/Sequence.h> // usage: see test/OrderedStatic @@ -37,17 +37,17 @@ { public: virtual void createObject() = 0; - + protected: OrderedStaticCreatorFunc(); virtual ~OrderedStaticCreatorFunc(); - + private: OrderedStaticCreatorFunc(const OrderedStaticCreatorFunc&); }; //////////////////////////////////////////////////////////////////////////////// - // template base clase for OrderedStatic template, + // template base clase for OrderedStatic template, // common for all specializations //////////////////////////////////////////////////////////////////////////////// template<class T> @@ -69,11 +69,11 @@ OrderedStaticBase(unsigned int longevity) : val_(0), longevity_(longevity) { } - + virtual ~OrderedStaticBase() { } - + void SetLongevity(T* ptr) { val_=ptr; @@ -86,11 +86,11 @@ OrderedStaticBase& operator=(const OrderedStaticBase&); T* val_; unsigned int longevity_; - + }; //////////////////////////////////////////////////////////////////////////////// - // OrderedStaticManagerClass implements details + // OrderedStaticManagerClass implements details // OrderedStaticManager is then defined as a Singleton //////////////////////////////////////////////////////////////////////////////// class LOKI_EXPORT OrderedStaticManagerClass @@ -107,7 +107,7 @@ private: OrderedStaticManagerClass(const OrderedStaticManagerClass&); OrderedStaticManagerClass& operator=(const OrderedStaticManagerClass&); - + struct Data { Data(unsigned int,OrderedStaticCreatorFunc*, Creator); @@ -129,7 +129,7 @@ typedef Loki::SingletonHolder < - Loki::Private::OrderedStaticManagerClass, + Loki::Private::OrderedStaticManagerClass, Loki::CreateUsingNew, Loki::NoDestroy, Loki::SingleThreaded @@ -137,7 +137,7 @@ OrderedStaticManager; //////////////////////////////////////////////////////////////////////////////// - // template OrderedStatic template: + // template OrderedStatic template: // L : longevity // T : object type // TList : creator parameters @@ -154,7 +154,7 @@ template<unsigned int L, class T> class OrderedStatic<L, T, Loki::NullType> : public Private::OrderedStaticBase<T> { - public: + public: OrderedStatic() : Private::OrderedStaticBase<T>(L) { OrderedStaticManager::Instance().registerObject @@ -180,7 +180,7 @@ OrderedStaticManager::Instance().registerObject (L,this,&Private::OrderedStaticCreatorFunc::createObject); } - + void createObject() { Private::OrderedStaticBase<T>::SetLongevity(new T(para_)); Modified: trunk/include/loki/Register.h =================================================================== --- trunk/include/loki/Register.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/Register.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2006 Peter K\xFCmmel -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_REGISTER_INC_ @@ -15,12 +15,12 @@ // $Id$ -#include "TypeManip.h" -#include "HierarchyGenerators.h" -#include "ForEachType.h" +#include <loki/TypeManip.h> +#include <loki/HierarchyGenerators.h> +#include <loki/ForEachType.h> -/// \defgroup RegisterGroup Register +/// \defgroup RegisterGroup Register namespace Loki { @@ -35,14 +35,14 @@ /// \ingroup RegisterGroup /// Must be specialized be the user //////////////////////////////////////////////////////////////////////////////// - template<class T> + template<class T> bool RegisterFunction(); //////////////////////////////////////////////////////////////////////////////// /// \ingroup RegisterGroup /// Must be specialized be the user //////////////////////////////////////////////////////////////////////////////// - template<class T> + template<class T> bool UnRegisterFunction(); namespace Private @@ -52,7 +52,7 @@ template< int Index, typename T > void operator()() { - RegisterFunction<T>(); + RegisterFunction<T>(); } }; @@ -118,8 +118,8 @@ /// see test/Register //////////////////////////////////////////////////////////////////////////////// - -#define LOKI_CONCATE(a,b,c,d) a ## b ## c ## d + +#define LOKI_CONCATE(a,b,c,d) a ## b ## c ## d #define LOKI_CONCAT(a,b,c,d) LOKI_CONCATE(a,b,c,d) #define LOKI_CHECK_CLASS_IN_LIST( CLASS , LIST ) \ Modified: trunk/include/loki/Sequence.h =================================================================== --- trunk/include/loki/Sequence.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/Sequence.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -15,7 +15,7 @@ // $Id$ -#include "Typelist.h" +#include <loki/Typelist.h> namespace Loki { Modified: trunk/include/loki/Singleton.h =================================================================== --- trunk/include/loki/Singleton.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/Singleton.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -18,8 +18,8 @@ // $Id$ -#include "LokiExport.h" -#include "Threads.h" +#include <loki/LokiExport.h> +#include <loki/Threads.h> #include <algorithm> #include <stdexcept> #include <cassert> Modified: trunk/include/loki/SmallObj.h =================================================================== --- trunk/include/loki/SmallObj.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/SmallObj.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -18,9 +18,9 @@ // $Id$ -#include "LokiExport.h" -#include "Threads.h" -#include "Singleton.h" +#include <loki/LokiExport.h> +#include <loki/Threads.h> +#include <loki/Singleton.h> #include <cstddef> #include <new> // needed for std::nothrow_t parameter. Modified: trunk/include/loki/SmartPtr.h =================================================================== --- trunk/include/loki/SmartPtr.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/SmartPtr.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -29,12 +29,12 @@ /// \defgroup SmartPointerCheckingGroup Checking policies /// \ingroup SmartPointerGroup -#include "LokiExport.h" -#include "SmallObj.h" -#include "TypeManip.h" -#include "static_check.h" -#include "RefToValue.h" -#include "ConstPolicy.h" +#include <loki/LokiExport.h> +#include <loki/SmallObj.h> +#include <loki/TypeManip.h> +#include <loki/static_check.h> +#include <loki/RefToValue.h> +#include <loki/ConstPolicy.h> #include <functional> #include <stdexcept> Modified: trunk/include/loki/TypeTraits.h =================================================================== --- trunk/include/loki/TypeTraits.h 2010-03-15 06:03:01 UTC (rev 1068) +++ trunk/include/loki/TypeTraits.h 2010-04-19 03:09:59 UTC (rev 1069) @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_TYPETRAITS_INC_ @@ -18,8 +18,8 @@ // $Id$ -#include "Typelist.h" -#include "Sequence.h" +#include <loki/Typelist.h> +#include <loki/Sequence.h> #if (defined _MSC_VER) && (_MSC_VER < 1400) #include <string> @@ -27,7 +27,7 @@ #ifdef _MSC_VER -#pragma warning( push ) +#pragma warning( push ) #pragma warning( disable : 4180 ) //qualifier applied to function type has no meaning; ignored #endif @@ -36,7 +36,7 @@ //////////////////////////////////////////////////////////////////////////////// // class template IsCustomUnsignedInt // Offers a means to integrate nonstandard built-in unsigned integral types -// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits // class template defined below. // Invocation: IsCustomUnsignedInt<T> where T is any type // Defines 'value', an enum that is 1 iff T is a custom built-in unsigned @@ -49,12 +49,12 @@ struct IsCustomUnsignedInt { enum { value = 0 }; - }; + }; //////////////////////////////////////////////////////////////////////////////// // class template IsCustomSignedInt // Offers a means to integrate nonstandard built-in unsigned integral types -// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits // class template defined below. // Invocation: IsCustomSignedInt<T> where T is any type // Defines 'value', an enum that is 1 iff T is a custom built-in signed @@ -67,7 +67,7 @@ struct IsCustomSignedInt { enum { value = 0 }; - }; + }; //////////////////////////////////////////////////////////////////////////////// // class template IsCustomFloat @@ -84,7 +84,7 @@ struct IsCustomFloat { enum { value = 0 }; - }; + }; //////////////////////////////////////////////////////////////////////////////// // Helper types for class template TypeTraits defined below @@ -92,14 +92,14 @@ namespace Private { -#ifndef LOKI_DISABLE_TYPELIST_MACROS - typedef LOKI_TYPELIST_4(unsigned char, unsigned short int,unsigned int, unsigned long int) +#ifndef LOKI_DISABLE_TYPELIST_MACROS + typedef LOKI_TYPELIST_4(unsigned char, unsigned short int,unsigned int, unsigned long int) StdUnsignedInts; - typedef LOKI_TYPELIST_4(signed char, short int,int, long int) + typedef LOKI_TYPELIST_4(signed char, short int,int, long int) StdSignedInts; - typedef LOKI_TYPELIST_3(bool, char, wchar_t) + typedef LOKI_TYPELIST_3(bool, char, wchar_t) StdOtherInts; - typedef LOKI_TYPELIST_3(float, double, long double) + typedef LOKI_TYPELIST_3(float, double, long double) StdFloats; #else typedef Loki::Seq<unsigned char, unsigned short int,unsigned int, unsigned long int>::Type @@ -111,7 +111,7 @@ typedef Loki::Seq<float, double, long double>::Type StdFloats; -#endif +#endif template <typename U> struct AddPointer { typedef U* Result; @@ -151,312 +151,312 @@ { typedef NullType Result; }; - + template <typename T> struct IsFunctionPointerRaw {enum{result = 0};}; template <typename T> - struct IsFunctionPointerRaw<T(*)()> + struct IsFunctionPointerRaw<T(*)()> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01> - struct IsFunctionPointerRaw<T(*)(P01)> + struct IsFunctionPointerRaw<T(*)(P01)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02> struct IsFunctionPointerRaw<T(*)( - P01, P02)> + P01, P02)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03)> + P01, P02, P03)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04)> + P01, P02, P03, P04)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05)> + P01, P02, P03, P04, P05)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06)> + P01, P02, P03, P04, P05, + P06)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07)> + P06, P07)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07, P08)> + P06, P07, P08)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07, P08, P09)> + P06, P07, P08, P09)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10)> + P06, P07, P08, P09, P10)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11)> + P11)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12)> + P11, P12)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12, P13)> + P11, P12, P13)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12, P13, P14)> + P11, P12, P13, P14)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12, P13, P14, P15)> + P11, P12, P13, P14, P15)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16)> + P16)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17)> + P16, P17)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17, typename P18> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17, P18)> + P16, P17, P18)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17, typename P18, typename P19> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17, P18, P19)> + P16, P17, P18, P19)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17, typename P18, typename P19, typename P20> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17, P18, P19, P20)> + P16, P17, P18, P19, P20)> {enum {result = 1};}; template <typename T> struct IsFunctionPointerRaw<T(*)( - ...)> + ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01> struct IsFunctionPointerRaw<T(*)( - P01, ...)> + P01, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02> struct IsFunctionPointerRaw<T(*)( - P01, P02, ...)> + P01, P02, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, ...)> + P01, P02, P03, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, ...)> + P01, P02, P03, P04, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - ...)> + ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, ...)> + P01, P02, P03, P04, P05, + P06, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07, ...)> + P06, P07, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07, P08, ...)> + P06, P07, P08, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, - P06, P07, P08, P09, ...)> + P06, P07, P08, P09, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - ...)> + ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, ...)> + P11, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12, ...)> + P11, P12, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12, P13, ...)> + P11, P12, P13, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14> struct IsFunctionPointerRaw<T(*)( P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, - P11, P12, P13, P14, ...)> + P11, P12, P13, P14, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15> @@ -464,376 +464,376 @@ P01, P02, P03, P04, P05, P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - ...)> + ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, ...)> + P16, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17, ...)> + P16, P17, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17, typename P18> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17, P18, ...)> + P16, P17, P18, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17, typename P18, typename P19> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, - P16, P17, P18, P19, ...)> + P16, P17, P18, P19, ...)> {enum {result = 1};}; - template <typename T, + template <typename T, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15, typename P16, typename P17, typename P18, typename P19, typename P20> struct IsFunctionPointerRaw<T(*)( - P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10, + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, - ...)> + ...)> {enum {result = 1};}; - - + + template <typename T> struct IsMemberFunctionPointerRaw {enum{result = 0};}; template <typename T, typename S> - struct IsMemberFunctionPointerRaw<T (S::*)()> + struct IsMemberFunctionPointerRaw<T (S::*)()> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01> - struct IsMemberFunctionPointerRaw<T (S::*)(P01)> + struct IsMemberFunctionPointerRaw<T (S::*)(P01)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02> struct IsMemberFunctionPointerRaw<T (S::*)( - P01, P02)> + P01, P02)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03> struct IsMemberFunctionPointerRaw<T (S::*)( - P01, P02, P03)> + P01, P02, P03)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04> struct IsMemberFunctionPointerRaw<T (S::*)( - P01, P02, P03, P04)> + P01, P02, P03, P04)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04, typename P05> struct IsMemberFunctionPointerRaw<T (S::*)( - P01, P02, P03, P04, P05)> + P01, P02, P03, P04, P05)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06> struct IsMemberFunctionPointerRaw<T (S::*)( - P01, P02, P03, P04, P05, - P06)> + P01, P02, P03, P04, P05, + P06)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07> struct IsMemberFunctionPointerRaw<T (S::*)( P01, P02, P03, P04, P05, - P06, P07)> + P06, P07)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08> struct IsMemberFunctionPointerRaw<T (S::*)( P01, P02, P03, P04, P05, - P06, P07, P08)> + P06, P07, P08)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09> struct IsMemberFunctionPointerRaw<T (S::*)( P01, P02, P03, P04, P05, - P06, P07, P08, P09)> + P06, P07, P08, P09)> {enum {result = 1};}; - template <typename T, typename S, + template <typename T, typename S, typename P01, typename P02, typename P03, typename P04, typename P05, typename P06, typename P07, typename P08, typename P09, typename P10> struct IsMemberFunctionPointerRaw<T (S::*)( P01, P02, P03, P04, P05, - P06, P07, P08, P09, P10)> + P06, P07, P08, P09, P10)> {enum {result = 1};}; - template <typename T, typename S, + temp... [truncated message content] |
From: <ric...@us...> - 2010-03-15 06:03:07
|
Revision: 1068 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1068&view=rev Author: rich_sposato Date: 2010-03-15 06:03:01 +0000 (Mon, 15 Mar 2010) Log Message: ----------- Fixed bug using patch by ryants. Modified Paths: -------------- trunk/src/SmallObj.cpp Modified: trunk/src/SmallObj.cpp =================================================================== --- trunk/src/SmallObj.cpp 2009-12-22 11:36:36 UTC (rev 1067) +++ trunk/src/SmallObj.cpp 2010-03-15 06:03:01 UTC (rev 1068) @@ -790,6 +790,8 @@ return false; // Use the "make-a-temp-and-swap" trick to remove excess capacity. Chunks( chunks_ ).swap( chunks_ ); + deallocChunk_ = &chunks_.front(); + allocChunk_ = &chunks_.back(); return true; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <syn...@us...> - 2009-12-22 11:36:44
|
Revision: 1067 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1067&view=rev Author: syntheticpp Date: 2009-12-22 11:36:36 +0000 (Tue, 22 Dec 2009) Log Message: ----------- gcc fixes, thanks to Roland Pabel Modified Paths: -------------- trunk/test/SmartPtr/main.cpp trunk/test/SmartPtr/strong.cpp Modified: trunk/test/SmartPtr/main.cpp =================================================================== --- trunk/test/SmartPtr/main.cpp 2009-12-22 11:35:46 UTC (rev 1066) +++ trunk/test/SmartPtr/main.cpp 2009-12-22 11:36:36 UTC (rev 1067) @@ -1143,7 +1143,7 @@ virtual ~Dog() {} }; -}; +} // ---------------------------------------------------------------------------- Modified: trunk/test/SmartPtr/strong.cpp =================================================================== --- trunk/test/SmartPtr/strong.cpp 2009-12-22 11:35:46 UTC (rev 1066) +++ trunk/test/SmartPtr/strong.cpp 2009-12-22 11:36:36 UTC (rev 1067) @@ -1213,7 +1213,7 @@ virtual ~Dog() {} }; -}; +} // ---------------------------------------------------------------------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |