diff --git a/src/common/visitordispatcher.hpp b/src/common/visitordispatcher.hpp index dcc28391b..4ed6a52e2 100644 --- a/src/common/visitordispatcher.hpp +++ b/src/common/visitordispatcher.hpp @@ -100,9 +100,9 @@ namespace lumiera /** - * For each posible call entry point via some subclass of the visitable hierarchy, + * For each possible call entry point via some subclass of the visitable hierarchy, * we maintain a dispatcher table to keep track of all concrete tool implementations - * able to recieve and process calls on objects of this subclass. + * able to receive and process calls on objects of this subclass. */ template class Dispatcher diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index c0172446e..32be6fa54 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -31,7 +31,13 @@ namespace lib { - + class AllocationCluster::MemoryManager + { + + }; + + + /** creating a new AllocationCluster prepares a table capable * of holding the individual object families to come. Each of those * is managed by a separate instance of the low-level memory manager. diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index 4e35f8485..f9c63eccf 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -27,7 +27,16 @@ ** segment are strongly interconnected, and thus each segment is ** being built in a single build process and is replaced or released ** as a whole. AllocationCluster implements memory management to - ** support this usage pattern. + ** support this usage pattern. + ** + ** @note this file is organised in a way which doesn't bind the + ** client code to the memory manager implementation. Parts of the + ** interface depending on the usage situation are implemented using + ** templates, and thus need to be in the header. This way they can + ** exploit the type information available in call context. This + ** information is passed to generic implementation functions + ** defined in allocationcluster.cpp . In a similar vein, the + ** AllocationCluster::MemoryManger is just forward declared. ** ** @see allocationclustertest.cpp ** @see builder::ToolFactory @@ -38,16 +47,20 @@ #ifndef LIB_ALLOCATIONCLUSTER_H #define LIB_ALLOCATIONCLUSTER_H -//#include +#include #include -//#include +#include #include +#include "common/multithread.hpp" +#include "common/error.hpp" +#include "common/util.hpp" + namespace lib { using std::string; -// using boost::scoped_ptr; + using boost::scoped_ptr; /** @@ -75,7 +88,7 @@ namespace lib { create () { TY* obj = new(allocation()) TY(); - return success(obj); + return commit(obj); } template @@ -83,7 +96,7 @@ namespace lib { create (P0& p0) { TY* obj = new(allocation()) TY (p0); - return success(obj); + return commit(obj); } template @@ -91,7 +104,7 @@ namespace lib { create (P0& p0, P1& p1) { TY* obj = new(allocation()) TY (p0,p1); - return success(obj); + return commit(obj); } template @@ -99,7 +112,7 @@ namespace lib { create (P0& p0, P1& p1, P2& p2) { TY* obj = new(allocation()) TY (p0,p1,p2); - return success(obj); + return commit(obj); } template @@ -107,7 +120,7 @@ namespace lib { create (P0& p0, P1& p1, P2& p2, P3& p3) { TY* obj = new(allocation()) TY (p0,p1,p2,p3); - return success(obj); + return commit(obj); } @@ -120,12 +133,135 @@ namespace lib { /** finish the allocation after the ctor is successful */ template TY& - success (TY* obj); + commit (TY* obj); + + + /** + * The type-specific configuration information + * any low-level memory manager needs to know + */ + struct TypeInfo; + + /** + * low-level memory manager responsible for + * the allocations of one specific type. + */ + class MemoryManager; + + /** + * organising the association Type -> table entry + */ + template + struct TypeSlot; + + static size_t maxTypeIDs; + + + typedef scoped_ptr PMemManager; + typedef std::vector ManagerTable; + ManagerTable typeHandlers_; + + + /** implementation of the actual memory allocation + * is pushed down to the MemoryManager impl. */ + void* initiateAlloc (PMemManager&); + + /** enrol the allocation after successful ctor call */ + void finishAlloc (PMemManager&, void*); + + /** create a new MemoryManager implementation */ + MemoryManager* setupMemoryManager (TypeInfo); }; - + + + + + + //-----implementation-details------------------------ + + struct AllocationCluster::TypeInfo + { + size_t allocSize; + void (*killIt)(void*); + + template + TypeInfo(TY*) + : allocSize(sizeof(TY)), + killIt(&TypeSlot::kill) + { } + }; + + template + struct AllocationCluster::TypeSlot + { + static size_t id_; ///< table pos of the memory manager in charge for type TY + + static PMemManager& + get(ManagerTable& handlers) + { + ENSURE (id_ < handlers.size() || 1 <= handlers.size()); // 0th Element used as "undefined" marker + + return handlers[id_ guard SIDEEFFECT; + if (!id_) + id_= ++maxTypeIDs; + if (id_ >= handlers.size()) + handlers.resize(id_); + if (!handlers[id_]) + handlers[id_].reset (setupMemoryManager (TypeInfo((TY*)0))); + } + + static void + kill (void* obj) + { + ASSERT (INSTANCEOF (TY,obj)); + TY* p = static_cast(obj); + ASSERT (p); + p->~TY(); + } + + }; + + + /** storage for static bookkeeping of type allocation slots */ + template + size_t AllocationCluster::TypeSlot::id_; + + size_t AllocationCluster::maxTypeIDs; + + - + + template + void* + AllocationCluster::allocation() + { + scoped_ptr typeHandler (TypeSlot::get (typeHandlers_)); + if (!typeHandler) + TypeSlot::setup (typeHandlers_); + return initiateAlloc (typeHandler); + } + + template + TY& + AllocationCluster::commit (TY* obj) + { + scoped_ptr typeHandler (TypeSlot::get (typeHandlers_)); + REQUIRE (typeHandler); + REQUIRE (obj); + finishAlloc (typeHandler, obj); + return *obj; + } + + + + } // namespace lib #endif