factor out and treat the attaching of objects separately
this is an advanced feature not required in the standard buffer usage cycle
This commit is contained in:
parent
ce25be6fa3
commit
55a77bdd73
6 changed files with 196 additions and 36 deletions
|
|
@ -57,7 +57,7 @@ namespace engine {
|
|||
* currently locked and usable by client code
|
||||
*/
|
||||
bool
|
||||
BufferProvider::verifyValidity (BufferDescriptor const& bufferID)
|
||||
BufferProvider::verifyValidity (BufferDescriptor const& bufferID) const
|
||||
{
|
||||
return meta_->isLocked (bufferID);
|
||||
}
|
||||
|
|
@ -184,6 +184,39 @@ namespace engine {
|
|||
ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
|
||||
|
||||
|
||||
|
||||
/** @warning this operation locally modifies the metadata entry of a single buffer
|
||||
* to attach a TypeHandler taking ownership of an object embedded within the buffer.
|
||||
* The client is responsible for actually placement-constructing the object; moreover
|
||||
* the client is responsible for any damage done to already existing buffer content.
|
||||
* @note the buffer must be in locked state and the underlying buffer type must not define
|
||||
* an non-trivial TypeDescriptor, because there is no clean way of superseding an
|
||||
* existing TypeDescriptor, which basically is just a functor and possibly
|
||||
* could perform any operation on buffer clean-up.
|
||||
* @note EX_STRONG
|
||||
*/
|
||||
void
|
||||
BufferProvider::attachTypeHandler (BuffHandle const& target, BufferDescriptor const& reference)
|
||||
{
|
||||
UNIMPLEMENTED ("convenience shortcut to attach/place an object in one sway");
|
||||
}
|
||||
|
||||
|
||||
/** @internal abort normal lifecycle, reset the underlying buffer and detach from it.
|
||||
* This allows to break out of normal usage and reset the handle to \em invalid state
|
||||
* @param invokeDtor if possibly the clean-up function of an TypeHandler registered with
|
||||
* the buffer metadata should be invoked prior to resetting the metadata state.
|
||||
* Default is \em not to invoke anything
|
||||
* @note EX_FREE
|
||||
*/
|
||||
void
|
||||
BufferProvider::emergencyCleanup (BuffHandle const& target, bool invokeDtor)
|
||||
{
|
||||
UNIMPLEMENTED ("emergency cleanup");
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BufferProvider::was_created_by_this_provider (BufferDescriptor const& descr) const
|
||||
{
|
||||
|
|
@ -231,5 +264,24 @@ namespace engine {
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
BuffHandle::emergencyCleanup()
|
||||
{
|
||||
descriptor_.provider_->emergencyCleanup(*this); // EX_FREE
|
||||
pBuffer_ = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BuffHandle::takeOwnershipFor(BufferDescriptor const& type)
|
||||
{
|
||||
if (this->size() < type.determineBufferSize())
|
||||
throw error::Logic ("insufficient buffer size to hold an instance of that type");
|
||||
|
||||
descriptor_.provider_->attachTypeHandler(*this, type); // EX_STRONG
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace engine
|
||||
|
|
|
|||
|
|
@ -106,6 +106,11 @@ namespace engine {
|
|||
template<typename BU>
|
||||
BuffHandle lockBufferFor ();
|
||||
|
||||
/** allow for attaching and owing an object within an already created buffer */
|
||||
void attachTypeHandler (BuffHandle const& target, BufferDescriptor const& reference);
|
||||
|
||||
void emergencyCleanup (BuffHandle const& target, bool invokeDtor =false);
|
||||
|
||||
|
||||
/** describe the kind of buffer managed by this provider */
|
||||
BufferDescriptor getDescriptorFor(size_t storageSize=0);
|
||||
|
|
@ -118,8 +123,8 @@ namespace engine {
|
|||
|
||||
/* === API for BuffHandle internal access === */
|
||||
|
||||
bool verifyValidity (BufferDescriptor const&);
|
||||
size_t getBufferSize (HashVal typeID) const;
|
||||
bool verifyValidity (BufferDescriptor const&) const;
|
||||
size_t getBufferSize (HashVal typeID) const;
|
||||
|
||||
protected:
|
||||
BuffHandle buildHandle (HashVal typeID, void* storage, LocalKey const&);
|
||||
|
|
|
|||
128
src/proc/engine/buffhandle-attach.hpp
Normal file
128
src/proc/engine/buffhandle-attach.hpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
BUFFHANDLE-ATTACH.hpp - Buffer handle extension to attach objects into the buffer
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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 buffhandle-attach.hpp
|
||||
** Extension to allow placing objects right into the buffers, taking ownership.
|
||||
** This extension is mostly helpful for writing unit-tests, and beyond that for the
|
||||
** rather unusual case where we need to place an full-blown object into the buffer,
|
||||
** instead of just plain data. A possible use case for this mechanism is to allow for
|
||||
** state pre calculation stream, feeding this local state to the individual render node
|
||||
** embedded into a "state frame". Some effect processors indeed need to maintain state
|
||||
** beyond the single frame (e.g. averaging, integrating, sound compression), which usually
|
||||
** is handled by applying an "instance" of that processor to the frames to be calculated
|
||||
** in a straight sequence.
|
||||
**
|
||||
** BuffHandle and the underlying BufferProvider standard implementation support that case
|
||||
** by attaching an object managing functor to the metadata. This way, the state can live
|
||||
** directly embedded into the frame and still be accessed like an object. To keep the
|
||||
** header and compilation footprint low, the implementation of the functions supporting
|
||||
** this special case was split out of the basic buffhandle.hpp
|
||||
**
|
||||
** @see BuffHandle
|
||||
** @see BufferProviderProtocol_test usage demonstration
|
||||
*/
|
||||
|
||||
#ifndef ENGINE_BUFFHANDLE_ATTACH_H
|
||||
#define ENGINE_BUFFHANDLE_ATTACH_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "proc/engine/buffer-provider.hpp"
|
||||
#include "proc/engine/buffhandle.hpp"
|
||||
|
||||
|
||||
namespace engine {
|
||||
|
||||
|
||||
|
||||
|
||||
/* === BuffHandle Implementation === */
|
||||
|
||||
|
||||
#define _EXCEPTION_SAFE_INVOKE(_CTOR_) \
|
||||
try \
|
||||
{ \
|
||||
return *new(pBuffer_) _CTOR_; \
|
||||
} \
|
||||
catch(...) \
|
||||
{ \
|
||||
emergencyCleanup(); /* EX_FREE */ \
|
||||
pBuffer_ = 0; \
|
||||
}
|
||||
|
||||
/** convenience shortcut: place and maintain an object within the buffer.
|
||||
* This operation performs the necessary steps to attach an object;
|
||||
* if the buffer isn't locked yet, it will do so. Moreover, the created
|
||||
* object will be owned by the buffer management facilities, i.e. the
|
||||
* destructor is registered as cleanup function.
|
||||
* @throw error::Logic in case there is already another TypeHandler registered
|
||||
* in charge of managing the buffer contents, or when the object to create
|
||||
* would not fit into this buffer.
|
||||
*/
|
||||
template<typename BU>
|
||||
inline BU&
|
||||
BuffHandle::create()
|
||||
{
|
||||
takeOwnershipFor<BU>();
|
||||
_EXCEPTION_SAFE_INVOKE (BU());
|
||||
}
|
||||
|
||||
#undef _EXCEPTION_SAFE_INVOKE
|
||||
|
||||
|
||||
|
||||
/** @internal helper to attach an TypeHandler after-the fact.
|
||||
* @note this prepares the buffer for placement-creating an embedded object.
|
||||
* It doesn't actually create an object
|
||||
* @throw error::Logic in case there is already another TypeHandler registered
|
||||
* in charge of managing the buffer contents, or when the object to create
|
||||
* would not fit into this buffer.
|
||||
*/
|
||||
template<typename BU>
|
||||
inline void
|
||||
BuffHandle::takeOwnershipFor()
|
||||
{
|
||||
BufferDescriptor howto_attach_object_automatically
|
||||
= descriptor_.provider_->getDescriptor<BU>();
|
||||
takeOwnershipFor (howto_attach_object_automatically); // EX_STRONG
|
||||
}
|
||||
|
||||
|
||||
/** convenience shortcut: access the buffer contents casted to a specific type.
|
||||
* @warning this is a \em blind cast, there is no type safety.
|
||||
* @note clients can utilise the metadata::LocalKey to keep track of some
|
||||
* specific property of the buffer, like e.g. the type of object.
|
||||
*/
|
||||
template<typename BU>
|
||||
inline BU&
|
||||
BuffHandle::accessAs()
|
||||
{
|
||||
if (!pBuffer_)
|
||||
throw error::Logic ("buffer not (yet) locked for access by clients"
|
||||
, LUMIERA_ERROR_LIFECYCLE);
|
||||
return *reinterpret_cast<BU*> (pBuffer_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace engine
|
||||
#endif
|
||||
|
|
@ -174,40 +174,15 @@ namespace engine {
|
|||
return descriptor_.determineBufferSize();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename BU>
|
||||
void takeOwnershipFor();
|
||||
void takeOwnershipFor(BufferDescriptor const& type);
|
||||
|
||||
void emergencyCleanup();
|
||||
};
|
||||
|
||||
|
||||
/* === Implementation details === */
|
||||
|
||||
/** convenience shortcut: place and maintain an object within the buffer.
|
||||
* This operation performs the necessary steps to attach an object;
|
||||
* if the buffer isn't locked yet, it will do so. Moreover, the created
|
||||
* object will be owned by the buffer management facilities, i.e. the
|
||||
* destructor is registered as cleanup function.
|
||||
*/
|
||||
template<typename BU>
|
||||
BU&
|
||||
BuffHandle::create()
|
||||
{
|
||||
UNIMPLEMENTED ("convenience shortcut to attach/place an object in one sway");
|
||||
}
|
||||
|
||||
|
||||
/** convenience shortcut: access the buffer contents casted to a specific type.
|
||||
* @warning this is a \em blind cast, there is no type safety.
|
||||
* @note clients can utilise the metadata::LocalKey to keep track of some
|
||||
* specific property of the buffer, like e.g. the type of object.
|
||||
*/
|
||||
template<typename BU>
|
||||
BU&
|
||||
BuffHandle::accessAs()
|
||||
{
|
||||
if (!pBuffer_)
|
||||
throw error::Logic ("buffer not (yet) locked for access by clients"
|
||||
, LUMIERA_ERROR_LIFECYCLE);
|
||||
return *reinterpret_cast<BU*> (pBuffer_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace engine
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
//#include "proc/play/diagnostic-output-slot.hpp"
|
||||
#include "proc/engine/testframe.hpp"
|
||||
#include "proc/engine/diagnostic-buffer-provider.hpp"
|
||||
#include "proc/engine/buffhandle.hpp"
|
||||
#include "proc/engine/buffhandle-attach.hpp"
|
||||
#include "proc/engine/bufftable.hpp"
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/test/run.hpp"
|
||||
#include "proc/engine/tracking-heap-block-provider.hpp"
|
||||
#include "proc/engine/buffhandle-attach.hpp"
|
||||
#include "proc/engine/testframe.hpp"
|
||||
#include "proc/engine/buffhandle.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
|
|
|||
Loading…
Reference in a new issue