diff --git a/src/lib/result.hpp b/src/lib/result.hpp index daf153a49..2f42c7f64 100644 --- a/src/lib/result.hpp +++ b/src/lib/result.hpp @@ -24,9 +24,9 @@ /** @file result.hpp ** Intermediary value object to represent the result of an operation. ** This operation might have produced a value result or failed with an exception. - ** Typically, the Result token used \em inline -- immediately either invoking one - ** of the member function or employing the built-in result type conversion. It - ** will be copyable iff the result value is copyable. There is an implicit + ** Typically, the Result token is used \em inline -- immediately either invoking + ** one of the member function or employing the built-in result type conversion. + ** It will be copyable iff the result value is copyable. There is an implicit ** valid or failure state, which can be tested. Any attempt to get the value ** of an invalid result token will cause in an exception to be thrown. ** diff --git a/src/lib/scoped-holder-transfer.hpp b/src/lib/scoped-holder-transfer.hpp index e1ee6d5c9..58508f393 100644 --- a/src/lib/scoped-holder-transfer.hpp +++ b/src/lib/scoped-holder-transfer.hpp @@ -105,8 +105,8 @@ namespace lib { pointer address(reference r) const { return par_.address(r); } const_pointer address(const_reference cr) const { return par_.address(cr); } pointer allocate(size_type n, const void *p=0){ return par_.allocate(n,p); } - void deallocate(pointer p, size_type n) { return par_.deallocate(p,n); } - void destroy(pointer p) { return par_.destroy(p); } + void deallocate(pointer p, size_type n) { par_.deallocate(p,n); } + void destroy(pointer p) { par_.destroy(p); } void diff --git a/src/lib/simple-allocator.hpp b/src/lib/simple-allocator.hpp new file mode 100644 index 000000000..71b0438fa --- /dev/null +++ b/src/lib/simple-allocator.hpp @@ -0,0 +1,262 @@ +/* + SIMPLE-ALLOCATOR.hpp - frontend for plain explicit allocations + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file simple-allocator.hpp + ** Frontend and marker interface for allocating small objects explicitly. + ** Contrary to the TypedAllocationManager, the SimpleAllocator doesn't provide any + ** ref-counting or tracking facilities, nor does he support bulk de-allocation. + ** Each object needs to be allocated and released by explicit call. + ** The advantage over using std::allocator directly is the shortcut for (placement) construction, + ** and -- of course -- the ability to exchange the memory model at one central location. + ** + ** SimpleAllocator instances will be defined for a specific collection of types; for each of those + ** types, there will be an embedded dedicated custom allocator (currently as of 9/2011, just + ** implemented as std::allocator). Objects of these preconfigured types can be constructed + ** and destroyed through this allocator instance. Each call needs to be done explicitly, with + ** the precise, concrete type to be created or destroyed. This is especially important for + ** the releasing of objects: there is \em no support for any kind of virtual destruction. + ** + ** @see engine::BufferMetadata + ** @see TypedAllocationManager (another more elaborate custom allocation scheme) + ** + */ + + + +#ifndef LIB_SIMPLE_ALLOCATOR_H +#define LIB_SIMPLE_ALLOCATOR_H + +//#include "pre.hpp" +#include "lib/error.hpp" +#include "lib/meta/generator.hpp" +#include "lib/format.hpp" +//#include "lib/typed-counter.hpp" +#include "include/logging.h" + + +//#include +#include +#include + + + +namespace lib { + +// using std::tr1::shared_ptr; + using lumiera::typelist::InstantiateForEach; + using lumiera::typelist::Types; + + namespace { + using lumiera::typelist::Node; + using lumiera::typelist::NullType; + + template + struct IsInList + { + enum{ value = false }; + }; + + template + struct IsInList, TY> + { + enum{ value = true }; + }; + + template + struct IsInList, TY> + { + enum{ value = IsInList::value }; + }; + + } + + + template + class CustomAllocator + : public std::allocator + { + + }; + + + + /** + * Frontend for explicit allocations, using a custom allocator. + * This template is to be instantiated for the collection of types + * later to be allocated through this custom memory manager/model. + * It provides convenience shortcuts for placement-construction + * and releasing of target objects. + * + * @todo currently (as of 8/09) the low-level pooled allocator + * isn't implemented; instead we do just heap allocations. + * see Ticket #835 + */ + template + class SimpleAllocator + : InstantiateForEach< typename TYPES::List // for each of those types... + , CustomAllocator // ...mix in the custom allocator + > + { + + /** forward plain memory allocation */ + template + XX * + allocateSlot () + { + TRACE (memory, "allocate %s", util::tyStr().c_str()); + return CustomAllocator::allocate (1); + } + + template + void + releaseSlot (XX* entry) + { + TRACE (memory, "release %s", util::tyStr().c_str()); + CustomAllocator::deallocate (entry, 1); + } + + + template + void + ___assertSupportedType() + { + typedef typename TYPES::List PreconfiguredTypes; + typedef IsInList IsPreconfiguredType; + + BOOST_STATIC_ASSERT (IsPreconfiguredType::value); + } + + + + + public: /* ==== build objects with managed allocation ==== */ + +#define _EXCEPTION_SAFE_INVOKE(_CTOR_) \ + \ + ___assertSupportedType(); \ + XX* storage = allocateSlot(); \ + try \ + { \ + return (new(storage) _CTOR_ ); \ + } \ + catch(...) \ + { \ + releaseSlot(storage); \ + throw; \ + } + + template< class XX> + XX* //_____________________ + create () ///< invoke default ctor + { + _EXCEPTION_SAFE_INVOKE ( XX() ) + } + + + template< class XX, typename P1> + XX* //___________________ + create (P1& p1) ///< invoke 1-arg ctor + { + _EXCEPTION_SAFE_INVOKE ( XX (p1) ) + } + + + template< class XX + , typename P1 + , typename P2 + > + XX* //___________________ + create (P1& p1, P2& p2) ///< invoke 2-arg ctor + { + _EXCEPTION_SAFE_INVOKE ( XX (p1,p2) ) + } + + + template< class XX + , typename P1 + , typename P2 + , typename P3 + > + XX* //___________________ + create (P1& p1, P2& p2, P3& p3) ///< invoke 3-arg ctor + { + _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3) ) + } + + + template< class XX + , typename P1 + , typename P2 + , typename P3 + , typename P4 + > + XX* //___________________ + create (P1& p1, P2& p2, P3& p3, P4& p4) ///< invoke 4-arg ctor + { + _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3,p4) ) + } + + + template< class XX + , typename P1 + , typename P2 + , typename P3 + , typename P4 + , typename P5 + > + XX* //___________________ + create (P1& p1, P2& p2, P3& p3, P4& p4, P5& p5) ///< invoke 5-arg ctor + { + _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3,p4,p5) ) + } + +#undef _EXCEPTION_SAFE_INVOKE + + + + template + void + destroy (XX* entry) + { + if (!entry) return; + ___assertSupportedType(); + try + { + entry->~XX(); + } + catch(...) + { + lumiera_err errorID = lumiera_error(); + WARN (common_dbg, "dtor of %s failed: %s", util::tyStr(entry).c_str() + , errorID ); + } + releaseSlot (entry); + } + + }; + + + + +} // namespace lib +#endif diff --git a/src/lib/typed-allocation-manager.hpp b/src/lib/typed-allocation-manager.hpp index 188f120dc..d1a04b19e 100644 --- a/src/lib/typed-allocation-manager.hpp +++ b/src/lib/typed-allocation-manager.hpp @@ -63,8 +63,8 @@ -#ifndef CONTROL_TYPED_ALLOCATION_MANAGER_H -#define CONTROL_TYPED_ALLOCATION_MANAGER_H +#ifndef LIB_TYPED_ALLOCATION_MANAGER_H +#define LIB_TYPED_ALLOCATION_MANAGER_H //#include "pre.hpp" #include "lib/error.hpp" diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index e71a60a10..d40fd0433 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -54,7 +54,6 @@ namespace control { - using lib::TypedAllocationManager; using lib::InPlaceBuffer; using std::string; diff --git a/src/proc/control/command-impl.hpp b/src/proc/control/command-impl.hpp index 7d3c18536..a25d92fad 100644 --- a/src/proc/control/command-impl.hpp +++ b/src/proc/control/command-impl.hpp @@ -57,7 +57,6 @@ namespace control { - using lib::TypedAllocationManager; using std::tr1::function; using std::tr1::shared_ptr; diff --git a/src/proc/engine/buffer-metadata.hpp b/src/proc/engine/buffer-metadata.hpp index c71359313..ae59f93f6 100644 --- a/src/proc/engine/buffer-metadata.hpp +++ b/src/proc/engine/buffer-metadata.hpp @@ -104,8 +104,11 @@ namespace engine { class Metadata { public: - struct Entry + class Entry { + + + public: BufferState state() const; HashVal parentKey() const; Entry& mark (BufferState newState); diff --git a/tests/40components.tests b/tests/40components.tests index a81b77d3b..9dfaffd74 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -1136,7 +1136,12 @@ return: 0 END -TEST "TypedAllocationManager" TypedAllocationManager_test < + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "lib/simple-allocator.hpp" +#include "lib/util.hpp" + + +//#include +#include +#include + + +namespace lib { +namespace test{ + + + using util::isSameObject; +// using std::tr1::shared_ptr; + using std::string; + using std::rand; + + + + namespace { // test data and helpers... + + long checksum_ = 0; + + /** + * Yet-another ctor/dtor-tracking test dummy object.... + */ + template + class DummyObj + { + char crap_[siz]; + + public: + DummyObj() + { + REQUIRE (siz); + for (uint i=0; i,DummyObj<23>,string> > TestAllocator; + } + + + + /*************************************************************************************** + * @test cover the basic operations of a custom allocator, delegating to mpool. + * The SimpleAllocator doesn't provide any ref-counting or tracking facilities, + * nor does he support bulk de-allocation. The advantage over using std::allocator + * directly is the shortcut for (placement) construction, and -- of course -- the + * ability to exchange the memory model at one central location. + * + * @todo as of 9/11 we do heap allocation, but we should use mpool -- see also Ticket #835 + * + * @see engine::BufferMetadata + * @see TypedAllocationManager_test + */ + class SimpleAllocator_test : public Test + { + + virtual void + run (Arg) + { + CHECK (0 == checksum_); + + TestAllocator allocator; + + typedef string * PS; + typedef DummyObj<1> * PD1; + typedef DummyObj<23> * PD23; + CHECK (sizeof(DummyObj<1>) != sizeof(DummyObj<23>)); + + PD1 pD11 = allocator.create >(); + PD1 pD12 = allocator.create >(); + PD23 pD21 = allocator.create >(); + PD23 pD22 = allocator.create >(); + PS pS11 = allocator.create ("Lumiera"); + PS pS12 = allocator.create ("the paradox"); + + CHECK (pD11); + CHECK (pD12); + CHECK (pD21); + CHECK (pD22); + CHECK (pS11); + CHECK (pS12); + CHECK (!isSameObject (*pD11, *pD12)); + CHECK (!isSameObject (*pD11, *pD21)); + CHECK (!isSameObject (*pD11, *pD22)); + CHECK (!isSameObject (*pD11, *pS11)); + CHECK (!isSameObject (*pD11, *pS12)); + CHECK (!isSameObject (*pD12, *pD21)); + CHECK (!isSameObject (*pD12, *pD22)); + CHECK (!isSameObject (*pD12, *pS11)); + CHECK (!isSameObject (*pD12, *pS12)); + CHECK (!isSameObject (*pD21, *pD22)); + CHECK (!isSameObject (*pD21, *pS11)); + CHECK (!isSameObject (*pD21, *pS12)); + CHECK (!isSameObject (*pD22, *pS11)); + CHECK (!isSameObject (*pD22, *pS12)); + CHECK (!isSameObject (*pS11, *pS12)); + + CHECK (*pS11 == "Lumiera"); + CHECK (*pS12 == "the paradox"); + + PD23 pDxx = allocator.create > (*pD21); + PS pSxx = allocator.create (*pS12); + + CHECK (*pS12 == *pSxx); + CHECK (!isSameObject (*pS12, *pSxx)); + + allocator.destroy (pD11); + allocator.destroy (pD12); + allocator.destroy (pD21); + allocator.destroy (pD22); + allocator.destroy (pS11); + allocator.destroy (pS12); + allocator.destroy (pDxx); + allocator.destroy (pSxx); + + CHECK (0 == checksum_); + } + }; + + + /** Register this test class... */ + LAUNCHER (SimpleAllocator_test, "unit common"); + + +}} // namespace lib::test