From ca0aa234799940edceaa90ddfdb91b98a528c6cd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 12 Nov 2011 00:36:53 +0100 Subject: [PATCH] BufferProvider default impl: attaching a type --- src/proc/engine/buffer-metadata.hpp | 118 +----------------- src/proc/engine/buffer-provider.cpp | 11 +- src/proc/engine/buffer-provider.hpp | 11 +- src/proc/engine/type-handler.hpp | 182 ++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 121 deletions(-) create mode 100644 src/proc/engine/type-handler.hpp diff --git a/src/proc/engine/buffer-metadata.hpp b/src/proc/engine/buffer-metadata.hpp index 57420fe7f..b06f01035 100644 --- a/src/proc/engine/buffer-metadata.hpp +++ b/src/proc/engine/buffer-metadata.hpp @@ -56,13 +56,11 @@ #include "lib/error.hpp" #include "lib/symbol.hpp" -#include "lib/functor-util.hpp" #include "lib/util-foreach.hpp" #include "include/logging.h" +#include "proc/engine/type-handler.hpp" -#include #include -#include #include @@ -71,9 +69,6 @@ namespace engine { using lib::HashVal; using lib::Literal; using util::for_each; - using std::tr1::bind; - using std::tr1::function; - using std::tr1::placeholders::_1; namespace error = lumiera::error; @@ -138,117 +133,6 @@ namespace engine { }; - namespace { // (optional) helpers to build an object embedded within the buffer... - - template - inline void - buildIntoBuffer (void* storageBuffer) - { - new(storageBuffer) X(); - } - - template - inline void - buildIntoBuffer_A1 (void* storageBuffer, A1 arg1) - { - new(storageBuffer) X(arg1); - } - - template - inline void - destroyInBuffer (void* storageBuffer) - { - X* embedded = static_cast (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 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 - TypeHandler(CTOR ctor, DTOR dtor) - : createAttached (ctor) - , destroyAttached (dtor) - { } - - /** builder function defining a TypeHandler - * to place a default-constructed object - * into the buffer. */ - template - static TypeHandler - create () - { - return TypeHandler (buildIntoBuffer, destroyInBuffer); - } - - template - static TypeHandler - create (A1 a1) - { - return TypeHandler ( bind (buildIntoBuffer_A1, _1, a1) - , destroyInBuffer); - } - - 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 diff --git a/src/proc/engine/buffer-provider.cpp b/src/proc/engine/buffer-provider.cpp index f0d1b337f..ea5e4f5f0 100644 --- a/src/proc/engine/buffer-provider.cpp +++ b/src/proc/engine/buffer-provider.cpp @@ -58,8 +58,15 @@ namespace engine { { return BufferDescriptor (*this, meta_->key (storageSize)); } - - + + + BufferDescriptor + BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment) + { + return BufferDescriptor (*this, meta_->key (storageSize, specialTreatment)); + } + + /* === BufferDescriptor and BuffHandle === */ diff --git a/src/proc/engine/buffer-provider.hpp b/src/proc/engine/buffer-provider.hpp index 368d54a4c..174555acf 100644 --- a/src/proc/engine/buffer-provider.hpp +++ b/src/proc/engine/buffer-provider.hpp @@ -45,6 +45,7 @@ #include "lib/error.hpp" #include "lib/symbol.hpp" #include "proc/engine/buffhandle.hpp" +#include "proc/engine/type-handler.hpp" #include #include @@ -92,6 +93,7 @@ namespace engine { /** describe the kind of buffer managed by this provider */ BufferDescriptor getDescriptorFor(size_t storageSize=0); + BufferDescriptor getDescriptorFor(size_t storageSize, TypeHandler specialTreatment); template BufferDescriptor getDescriptor(); @@ -120,15 +122,20 @@ namespace engine { BuffHandle BufferProvider::lockBufferFor() { - UNIMPLEMENTED ("convenience shortcut to announce and lock for a specific object type"); + BufferDescriptor buffer_to_attach_object = getDescriptor(); + 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 BufferDescriptor BufferProvider::getDescriptor() { - UNIMPLEMENTED ("build descriptor for automatically placing an object instance into the buffer"); + return getDescriptorFor (sizeof(BU), TypeHandler::create()); } diff --git a/src/proc/engine/type-handler.hpp b/src/proc/engine/type-handler.hpp new file mode 100644 index 000000000..d7130d308 --- /dev/null +++ b/src/proc/engine/type-handler.hpp @@ -0,0 +1,182 @@ +/* + TYPE-HANDLER.hpp - a functor pair for setup and destruction + + 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 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 +#include + + +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 + inline void + buildIntoBuffer (void* storageBuffer) + { + new(storageBuffer) X(); + } + + template + inline void + buildIntoBuffer_A1 (void* storageBuffer, A1 arg1) + { + new(storageBuffer) X(arg1); + } + + template + inline void + destroyInBuffer (void* storageBuffer) + { + X* embedded = static_cast (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 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 + TypeHandler(CTOR ctor, DTOR dtor) + : createAttached (ctor) + , destroyAttached (dtor) + { } + + /** builder function defining a TypeHandler + * to place a default-constructed object + * into the buffer. */ + template + static TypeHandler + create () + { + return TypeHandler (buildIntoBuffer, destroyInBuffer); + } + + template + static TypeHandler + create (A1 a1) + { + return TypeHandler ( bind (buildIntoBuffer_A1, _1, a1) + , destroyInBuffer); + } + + 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