CrystalSpace

Public API Reference

csutil/pooledscfclass.h
Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2004 by Jorrit Tyberghein
00003               (C) 2004 by Frank Richter
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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     /* A bit nasty: set scfPool member of the (still unconstructed!) 
00127      * instance... */
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__

Generated for Crystal Space 2.0 by doxygen 1.7.6.1