finished the outline
This commit is contained in:
parent
1b6df94aab
commit
74164e890e
3 changed files with 157 additions and 15 deletions
|
|
@ -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 TAR, class TOOL>
|
||||
class Dispatcher
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
//#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#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>()) TY();
|
||||
return success(obj);
|
||||
return commit(obj);
|
||||
}
|
||||
|
||||
template<class TY, typename P0>
|
||||
|
|
@ -83,7 +96,7 @@ namespace lib {
|
|||
create (P0& p0)
|
||||
{
|
||||
TY* obj = new(allocation<TY>()) TY (p0);
|
||||
return success(obj);
|
||||
return commit(obj);
|
||||
}
|
||||
|
||||
template<class TY, typename P0, typename P1>
|
||||
|
|
@ -91,7 +104,7 @@ namespace lib {
|
|||
create (P0& p0, P1& p1)
|
||||
{
|
||||
TY* obj = new(allocation<TY>()) TY (p0,p1);
|
||||
return success(obj);
|
||||
return commit(obj);
|
||||
}
|
||||
|
||||
template<class TY, typename P0, typename P1, typename P2>
|
||||
|
|
@ -99,7 +112,7 @@ namespace lib {
|
|||
create (P0& p0, P1& p1, P2& p2)
|
||||
{
|
||||
TY* obj = new(allocation<TY>()) TY (p0,p1,p2);
|
||||
return success(obj);
|
||||
return commit(obj);
|
||||
}
|
||||
|
||||
template<class TY, typename P0, typename P1, typename P2, typename P3>
|
||||
|
|
@ -107,7 +120,7 @@ namespace lib {
|
|||
create (P0& p0, P1& p1, P2& p2, P3& p3)
|
||||
{
|
||||
TY* obj = new(allocation<TY>()) 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<class TY>
|
||||
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<class TY>
|
||||
struct TypeSlot;
|
||||
|
||||
static size_t maxTypeIDs;
|
||||
|
||||
|
||||
typedef scoped_ptr<MemoryManager> PMemManager;
|
||||
typedef std::vector<PMemManager> 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<class TY>
|
||||
TypeInfo(TY*)
|
||||
: allocSize(sizeof(TY)),
|
||||
killIt(&TypeSlot<TY>::kill)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class TY>
|
||||
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_<handlers.size()? id_ : 0 ];
|
||||
}
|
||||
|
||||
static void
|
||||
setup(ManagerTable& handlers)
|
||||
{
|
||||
lumiera::Thread::Lock<AllocationCluster> 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<TY*>(obj);
|
||||
ASSERT (p);
|
||||
p->~TY();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** storage for static bookkeeping of type allocation slots */
|
||||
template<class TY>
|
||||
size_t AllocationCluster::TypeSlot<TY>::id_;
|
||||
|
||||
size_t AllocationCluster::maxTypeIDs;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class TY>
|
||||
void*
|
||||
AllocationCluster::allocation()
|
||||
{
|
||||
scoped_ptr<MemoryManager> typeHandler (TypeSlot<TY>::get (typeHandlers_));
|
||||
if (!typeHandler)
|
||||
TypeSlot<TY>::setup (typeHandlers_);
|
||||
return initiateAlloc (typeHandler);
|
||||
}
|
||||
|
||||
template<class TY>
|
||||
TY&
|
||||
AllocationCluster::commit (TY* obj)
|
||||
{
|
||||
scoped_ptr<MemoryManager> typeHandler (TypeSlot<TY>::get (typeHandlers_));
|
||||
REQUIRE (typeHandler);
|
||||
REQUIRE (obj);
|
||||
finishAlloc (typeHandler, obj);
|
||||
return *obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace lib
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue