00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __CS_UTIL_POOLEDSCFCLASS_H__
00021 #define __CS_UTIL_POOLEDSCFCLASS_H__
00022
00031 #include "csutil/scf.h"
00032 #include "csutil/threading/atomicops.h"
00033 #include "csutil/threading/mutex.h"
00034
00035 #include "csutil/custom_new_disable.h"
00036
00064 template<typename Super, typename Allocator = CS::Memory::AllocatorMalloc,
00065 bool Locked = false>
00066 class scfImplementationPooled : public Super
00067 {
00068 typedef typename Super::scfClassType scfClassType;
00069 public:
00070 typedef scfImplementationPooled<Super, Allocator, Locked>
00071 scfPooledImplementationType;
00072
00073 class Pool : public CS::Threading::OptionalMutex<Locked>
00074 {
00075 friend class scfImplementationPooled<Super, Allocator, Locked>;
00076 struct Entry
00077 {
00078 Entry* next;
00079 };
00080 CS::Memory::AllocatorPointerWrapper<Entry, Allocator> pool;
00081 size_t allocedEntries;
00082 public:
00083 Pool () : pool ((Entry*)0), allocedEntries (0)
00084 {
00085 }
00086 Pool (const Allocator& alloc) : pool (alloc, 0), allocedEntries (0)
00087 {
00088 }
00089 ~Pool ()
00090 {
00091 while (pool.p != 0)
00092 {
00093 Entry* n = pool.p->next;
00094 pool.Free (pool.p);
00095 pool.p = n;
00096 }
00097 CS_ASSERT_MSG ("not all SCF-pooled instances released",
00098 allocedEntries == 0);
00099 }
00100 };
00101 protected:
00103 Pool* scfPool;
00104 public:
00106 inline void* operator new (size_t n, Pool& p)
00107 {
00108 typedef typename Pool::Entry PoolEntry;
00109 CS_ASSERT_MSG ("Alloc size mismatches class size expected for pooled "
00110 "allocation", n == sizeof (scfClassType));
00111 PoolEntry* newEntry;
00112 {
00113 CS::Threading::ScopedLock<Pool> lock (p);
00114 if (p.pool.p != 0)
00115 {
00116 newEntry = p.pool.p;
00117 p.pool.p = p.pool.p->next;
00118 }
00119 else
00120 {
00121 newEntry = static_cast<PoolEntry*> (p.pool.Alloc (n));
00122 }
00123 p.allocedEntries++;
00124 }
00125 scfClassType* newInst = reinterpret_cast<scfClassType*> (newEntry);
00126
00127
00128 static_cast<scfPooledImplementationType*> (newInst)->scfPool = &p;
00129 return newInst;
00130 }
00131
00133
00134 inline void operator delete (void* instance, Pool& p)
00135 {
00136 typedef typename Pool::Entry PoolEntry;
00137 PoolEntry* entry = static_cast<PoolEntry*> (instance);
00138 {
00139 CS::Threading::ScopedLock<Pool> lock (p);
00140 entry->next = p.pool.p;
00141 p.pool.p = entry;
00142 p.allocedEntries--;
00143 }
00144 }
00145 inline void operator delete (void* instance)
00146 {
00147 scfClassType* object = static_cast<scfClassType*> (instance);
00148 Pool& p = *(static_cast<scfImplementationPooled*> (object)->scfPool);
00149 scfImplementationPooled::operator delete (object, p);
00150 }
00152
00154 void DecRef ()
00155 {
00156 csRefTrackerAccess::TrackDecRef (this->GetSCFObject(), this->scfRefCount);
00157 if (CS::Threading::AtomicOperations::Decrement (&this->scfRefCount) == 0)
00158 {
00159 delete this->GetSCFObject();
00160 }
00161 }
00162
00164
00167 scfImplementationPooled (scfClassType* object) :
00168 Super (object) {}
00169 template<typename A>
00170 scfImplementationPooled (scfClassType* object, A a) :
00171 Super (object, a) {}
00172 template<typename A, typename B>
00173 scfImplementationPooled (scfClassType* object, A a, B b) :
00174 Super (object, a, b) {}
00175 template<typename A, typename B, typename C>
00176 scfImplementationPooled (scfClassType* object, A a, B b, C c) :
00177 Super (object, a, b, c) {}
00178 template<typename A, typename B, typename C, typename D>
00179 scfImplementationPooled (scfClassType* object, A a, B b, C c, D d) :
00180 Super (object, a, b, c, d) {}
00181 template<typename A, typename B, typename C, typename D, typename E>
00182 scfImplementationPooled (scfClassType* object, A a, B b, C c, D d, E e) :
00183 Super (object, a, b, c, d, e) {}
00185 };
00186
00189 #include "csutil/custom_new_enable.h"
00190
00191 #endif // __CS_UTIL_POOLEDSCFCLASS_H__