BufferProvider default impl: attaching a type
This commit is contained in:
parent
fd94367b9e
commit
ca0aa23479
4 changed files with 201 additions and 121 deletions
|
|
@ -56,13 +56,11 @@
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "lib/symbol.hpp"
|
#include "lib/symbol.hpp"
|
||||||
#include "lib/functor-util.hpp"
|
|
||||||
#include "lib/util-foreach.hpp"
|
#include "lib/util-foreach.hpp"
|
||||||
#include "include/logging.h"
|
#include "include/logging.h"
|
||||||
|
#include "proc/engine/type-handler.hpp"
|
||||||
|
|
||||||
#include <tr1/functional>
|
|
||||||
#include <tr1/unordered_map>
|
#include <tr1/unordered_map>
|
||||||
#include <boost/functional/hash.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -71,9 +69,6 @@ namespace engine {
|
||||||
using lib::HashVal;
|
using lib::HashVal;
|
||||||
using lib::Literal;
|
using lib::Literal;
|
||||||
using util::for_each;
|
using util::for_each;
|
||||||
using std::tr1::bind;
|
|
||||||
using std::tr1::function;
|
|
||||||
using std::tr1::placeholders::_1;
|
|
||||||
|
|
||||||
namespace error = lumiera::error;
|
namespace error = lumiera::error;
|
||||||
|
|
||||||
|
|
@ -138,117 +133,6 @@ namespace engine {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace { // (optional) helpers to build an object embedded within the buffer...
|
|
||||||
|
|
||||||
template<class X>
|
|
||||||
inline void
|
|
||||||
buildIntoBuffer (void* storageBuffer)
|
|
||||||
{
|
|
||||||
new(storageBuffer) X();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class X, typename A1>
|
|
||||||
inline void
|
|
||||||
buildIntoBuffer_A1 (void* storageBuffer, A1 arg1)
|
|
||||||
{
|
|
||||||
new(storageBuffer) X(arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class X>
|
|
||||||
inline void
|
|
||||||
destroyInBuffer (void* storageBuffer)
|
|
||||||
{
|
|
||||||
X* embedded = static_cast<X*> (storageBuffer);
|
|
||||||
embedded->~X();
|
|
||||||
}
|
|
||||||
}//(End)placement-new helpers
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pair of functors to maintain a datastructure within the buffer.
|
|
||||||
* TypeHandler describes how to outfit the buffer in a specific way.
|
|
||||||
* When defined, the buffer will be prepared when locking and cleanup
|
|
||||||
* will be invoked automatically when releasing. Especially, this
|
|
||||||
* can be used to \em attach an object to the buffer (placement-new)
|
|
||||||
*/
|
|
||||||
struct TypeHandler
|
|
||||||
{
|
|
||||||
typedef function<void(void*)> DoInBuffer;
|
|
||||||
|
|
||||||
DoInBuffer createAttached;
|
|
||||||
DoInBuffer destroyAttached;
|
|
||||||
|
|
||||||
/** build an invalid NIL TypeHandler */
|
|
||||||
TypeHandler()
|
|
||||||
: createAttached()
|
|
||||||
, destroyAttached()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/** build a TypeHandler
|
|
||||||
* binding to arbitrary constructor and destructor functions.
|
|
||||||
* On invocation, these functions get a void* to the buffer.
|
|
||||||
* @note the functor objects created from these operations
|
|
||||||
* might be shared for handling multiple buffers.
|
|
||||||
* Be careful with any state or arguments.
|
|
||||||
*/
|
|
||||||
template<typename CTOR, typename DTOR>
|
|
||||||
TypeHandler(CTOR ctor, DTOR dtor)
|
|
||||||
: createAttached (ctor)
|
|
||||||
, destroyAttached (dtor)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/** builder function defining a TypeHandler
|
|
||||||
* to place a default-constructed object
|
|
||||||
* into the buffer. */
|
|
||||||
template<class X>
|
|
||||||
static TypeHandler
|
|
||||||
create ()
|
|
||||||
{
|
|
||||||
return TypeHandler (buildIntoBuffer<X>, destroyInBuffer<X>);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class X, typename A1>
|
|
||||||
static TypeHandler
|
|
||||||
create (A1 a1)
|
|
||||||
{
|
|
||||||
return TypeHandler ( bind (buildIntoBuffer_A1<X,A1>, _1, a1)
|
|
||||||
, destroyInBuffer<X>);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
isValid() const
|
|
||||||
{
|
|
||||||
return bool(createAttached)
|
|
||||||
&& bool(destroyAttached);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend HashVal
|
|
||||||
hash_value (TypeHandler const& handler)
|
|
||||||
{
|
|
||||||
HashVal hash(0);
|
|
||||||
if (handler.isValid())
|
|
||||||
{
|
|
||||||
boost::hash_combine(hash, handler.createAttached);
|
|
||||||
boost::hash_combine(hash, handler.destroyAttached);
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool
|
|
||||||
operator== (TypeHandler const& left, TypeHandler const& right)
|
|
||||||
{
|
|
||||||
return (!left.isValid() && !right.isValid())
|
|
||||||
|| ( util::rawComparison(left.createAttached, right.createAttached)
|
|
||||||
&& util::rawComparison(left.destroyAttached, right.destroyAttached)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
friend bool
|
|
||||||
operator!= (TypeHandler const& left, TypeHandler const& right)
|
|
||||||
{
|
|
||||||
return !(left == right);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
namespace { // internal constants to mark the default case
|
namespace { // internal constants to mark the default case
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,13 @@ namespace engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BufferDescriptor
|
||||||
|
BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment)
|
||||||
|
{
|
||||||
|
return BufferDescriptor (*this, meta_->key (storageSize, specialTreatment));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* === BufferDescriptor and BuffHandle === */
|
/* === BufferDescriptor and BuffHandle === */
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "lib/symbol.hpp"
|
#include "lib/symbol.hpp"
|
||||||
#include "proc/engine/buffhandle.hpp"
|
#include "proc/engine/buffhandle.hpp"
|
||||||
|
#include "proc/engine/type-handler.hpp"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
@ -92,6 +93,7 @@ namespace engine {
|
||||||
|
|
||||||
/** describe the kind of buffer managed by this provider */
|
/** describe the kind of buffer managed by this provider */
|
||||||
BufferDescriptor getDescriptorFor(size_t storageSize=0);
|
BufferDescriptor getDescriptorFor(size_t storageSize=0);
|
||||||
|
BufferDescriptor getDescriptorFor(size_t storageSize, TypeHandler specialTreatment);
|
||||||
|
|
||||||
template<typename BU>
|
template<typename BU>
|
||||||
BufferDescriptor getDescriptor();
|
BufferDescriptor getDescriptor();
|
||||||
|
|
@ -120,15 +122,20 @@ namespace engine {
|
||||||
BuffHandle
|
BuffHandle
|
||||||
BufferProvider::lockBufferFor()
|
BufferProvider::lockBufferFor()
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("convenience shortcut to announce and lock for a specific object type");
|
BufferDescriptor buffer_to_attach_object = getDescriptor<BU>();
|
||||||
|
return lockBufferFor (buffer_to_attach_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** define a "buffer type" for automatically creating
|
||||||
|
* an instance of the template type embedded into the buffer
|
||||||
|
* and destroying that embedded object when releasing the buffer.
|
||||||
|
*/
|
||||||
template<typename BU>
|
template<typename BU>
|
||||||
BufferDescriptor
|
BufferDescriptor
|
||||||
BufferProvider::getDescriptor()
|
BufferProvider::getDescriptor()
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("build descriptor for automatically placing an object instance into the buffer");
|
return getDescriptorFor (sizeof(BU), TypeHandler::create<BU>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
182
src/proc/engine/type-handler.hpp
Normal file
182
src/proc/engine/type-handler.hpp
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
TYPE-HANDLER.hpp - a functor pair for setup and destruction
|
||||||
|
|
||||||
|
Copyright (C) Lumiera.org
|
||||||
|
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||||
|
|
||||||
|
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 type-handler.hpp
|
||||||
|
** Helper holding a pair of type-build-up and destruction functors.
|
||||||
|
** Basically these two functors embody all type specific knowledge required
|
||||||
|
** to place an object into some buffer space and to clean up later. They may even
|
||||||
|
** be used in a more unspecific way, e.g. just to "prepare" a buffer or frame and to
|
||||||
|
** "clean up" after usage.
|
||||||
|
**
|
||||||
|
** Within the Lumiera Engine, the BufferProvider default implementation utilises instances
|
||||||
|
** of TypeHandler to \em describe specific buffer types capable of managing an attached object,
|
||||||
|
** or requiring some other kind of special treatment of the memory area used for the buffer.
|
||||||
|
** This BufferDescriptor is embodied into the BufferMetadata::Key and used later on to invoke
|
||||||
|
** the contained ctor / dtor functors, passing a concrete buffer (memory area).
|
||||||
|
**
|
||||||
|
** @see buffer-metadata.hpp
|
||||||
|
** @see buffer-provider.hpp
|
||||||
|
** @see BufferMetadataKey_test#verifyTypeHandler unit-test
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROC_ENGINE_TYPE_HANDLER_H
|
||||||
|
#define PROC_ENGINE_TYPE_HANDLER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "lib/error.hpp"
|
||||||
|
#include "lib/functor-util.hpp"
|
||||||
|
|
||||||
|
#include <tr1/functional>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace engine {
|
||||||
|
|
||||||
|
using lib::HashVal;
|
||||||
|
using std::tr1::bind;
|
||||||
|
using std::tr1::function;
|
||||||
|
using std::tr1::placeholders::_1;
|
||||||
|
|
||||||
|
namespace error = lumiera::error;
|
||||||
|
|
||||||
|
|
||||||
|
namespace { // (optional) helpers to build an object embedded into a buffer...
|
||||||
|
|
||||||
|
template<class X>
|
||||||
|
inline void
|
||||||
|
buildIntoBuffer (void* storageBuffer)
|
||||||
|
{
|
||||||
|
new(storageBuffer) X();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class X, typename A1>
|
||||||
|
inline void
|
||||||
|
buildIntoBuffer_A1 (void* storageBuffer, A1 arg1)
|
||||||
|
{
|
||||||
|
new(storageBuffer) X(arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class X>
|
||||||
|
inline void
|
||||||
|
destroyInBuffer (void* storageBuffer)
|
||||||
|
{
|
||||||
|
X* embedded = static_cast<X*> (storageBuffer);
|
||||||
|
embedded->~X();
|
||||||
|
}
|
||||||
|
}//(End)placement-new helpers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pair of functors to maintain a datastructure within a buffer.
|
||||||
|
* TypeHandler describes how to outfit the buffer in a specific way.
|
||||||
|
* Special convenience builder function(s) are provided to create a
|
||||||
|
* TypeHandler performing placement-new into a buffer given on invocation.
|
||||||
|
* @note engine::BufferMetadata uses a TypeHandler to represent any
|
||||||
|
* special treatment of a buffer space. When defined, the buffer
|
||||||
|
* will be prepared on locking and cleanup will be invoked
|
||||||
|
* automatically when releasing.
|
||||||
|
* @warning comparison and hash values rely on internals of the
|
||||||
|
* tr1::function implementation and might not be 100% accurate
|
||||||
|
*/
|
||||||
|
struct TypeHandler
|
||||||
|
{
|
||||||
|
typedef function<void(void*)> DoInBuffer;
|
||||||
|
|
||||||
|
DoInBuffer createAttached;
|
||||||
|
DoInBuffer destroyAttached;
|
||||||
|
|
||||||
|
/** build an invalid NIL TypeHandler */
|
||||||
|
TypeHandler()
|
||||||
|
: createAttached()
|
||||||
|
, destroyAttached()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/** build a TypeHandler
|
||||||
|
* binding to arbitrary constructor and destructor functions.
|
||||||
|
* On invocation, these functions get a void* to the buffer.
|
||||||
|
* @note the functor objects created from these operations
|
||||||
|
* might be shared for handling multiple buffers.
|
||||||
|
* Be careful with any state or arguments.
|
||||||
|
*/
|
||||||
|
template<typename CTOR, typename DTOR>
|
||||||
|
TypeHandler(CTOR ctor, DTOR dtor)
|
||||||
|
: createAttached (ctor)
|
||||||
|
, destroyAttached (dtor)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/** builder function defining a TypeHandler
|
||||||
|
* to place a default-constructed object
|
||||||
|
* into the buffer. */
|
||||||
|
template<class X>
|
||||||
|
static TypeHandler
|
||||||
|
create ()
|
||||||
|
{
|
||||||
|
return TypeHandler (buildIntoBuffer<X>, destroyInBuffer<X>);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class X, typename A1>
|
||||||
|
static TypeHandler
|
||||||
|
create (A1 a1)
|
||||||
|
{
|
||||||
|
return TypeHandler ( bind (buildIntoBuffer_A1<X,A1>, _1, a1)
|
||||||
|
, destroyInBuffer<X>);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isValid() const
|
||||||
|
{
|
||||||
|
return bool(createAttached)
|
||||||
|
&& bool(destroyAttached);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend HashVal
|
||||||
|
hash_value (TypeHandler const& handler)
|
||||||
|
{
|
||||||
|
HashVal hash(0);
|
||||||
|
if (handler.isValid())
|
||||||
|
{
|
||||||
|
boost::hash_combine(hash, handler.createAttached);
|
||||||
|
boost::hash_combine(hash, handler.destroyAttached);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool
|
||||||
|
operator== (TypeHandler const& left, TypeHandler const& right)
|
||||||
|
{
|
||||||
|
return (!left.isValid() && !right.isValid())
|
||||||
|
|| ( util::rawComparison(left.createAttached, right.createAttached)
|
||||||
|
&& util::rawComparison(left.destroyAttached, right.destroyAttached)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
friend bool
|
||||||
|
operator!= (TypeHandler const& left, TypeHandler const& right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace engine
|
||||||
|
#endif
|
||||||
Loading…
Reference in a new issue