2008-07-16 05:09:04 +02:00
|
|
|
|
/*
|
2011-07-09 02:17:37 +02:00
|
|
|
|
BufferProvider - Abstraction for Buffer management during playback/render
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2008, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
**Lumiera** 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. See the file COPYING for further details.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
* *****************************************************************/
|
2008-07-16 05:09:04 +02:00
|
|
|
|
|
|
|
|
|
|
|
2016-11-03 18:22:31 +01:00
|
|
|
|
/** @file buffer-provider.cpp
|
2016-11-09 19:13:52 +01:00
|
|
|
|
** Implementation details related to buffer lifecycle management in the render engine.
|
2016-11-03 18:20:10 +01:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-15 04:47:31 +01:00
|
|
|
|
#include "lib/error.hpp"
|
2018-11-15 23:42:43 +01:00
|
|
|
|
#include "steam/engine/buffer-provider.hpp"
|
|
|
|
|
|
#include "steam/engine/buffer-metadata.hpp"
|
2011-11-13 04:20:14 +01:00
|
|
|
|
#include "lib/util.hpp"
|
2011-09-22 18:57:06 +02:00
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
using util::isSameAdr;
|
2008-07-16 05:09:04 +02:00
|
|
|
|
|
2018-11-15 23:55:13 +01:00
|
|
|
|
namespace steam {
|
2008-07-16 05:09:04 +02:00
|
|
|
|
namespace engine {
|
2011-09-04 01:54:36 +02:00
|
|
|
|
|
2024-07-27 17:17:02 +02:00
|
|
|
|
// storage for the default-marker constants
|
|
|
|
|
|
const TypeHandler TypeHandler::RAW{};
|
|
|
|
|
|
const LocalTag LocalTag::UNKNOWN{};
|
|
|
|
|
|
|
2011-09-04 01:54:36 +02:00
|
|
|
|
|
|
|
|
|
|
namespace { // impl. details and definitions
|
|
|
|
|
|
|
|
|
|
|
|
const uint DEFAULT_DESCRIPTOR = 0;
|
2011-09-21 02:23:12 +02:00
|
|
|
|
|
2011-09-04 01:54:36 +02:00
|
|
|
|
}
|
2011-11-14 01:43:29 +01:00
|
|
|
|
|
|
|
|
|
|
LUMIERA_ERROR_DEFINE (BUFFER_MANAGEMENT, "Problem providing working buffers");
|
|
|
|
|
|
|
2011-09-23 15:31:20 +02:00
|
|
|
|
|
2011-11-20 01:35:52 +01:00
|
|
|
|
/** build a new provider instance, managing a family of buffers.
|
|
|
|
|
|
* The metadata of these buffers is organised hierarchically based on
|
|
|
|
|
|
* chained hash values, using the #implementationID as a seed.
|
|
|
|
|
|
* @param implementationID symbolic ID setting these family of buffers apart.
|
|
|
|
|
|
*/
|
2011-09-23 15:31:20 +02:00
|
|
|
|
BufferProvider::BufferProvider (Literal implementationID)
|
2011-10-28 01:18:22 +02:00
|
|
|
|
: meta_(new BufferMetadata (implementationID))
|
2011-09-23 15:31:20 +02:00
|
|
|
|
{ }
|
|
|
|
|
|
|
2011-07-09 02:17:37 +02:00
|
|
|
|
BufferProvider::~BufferProvider() { }
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-09-04 01:54:36 +02:00
|
|
|
|
/** @internal verify the given descriptor.
|
|
|
|
|
|
* @return true if it corresponds to a buffer
|
|
|
|
|
|
* currently locked and usable by client code
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BufferProvider::verifyValidity (BuffDescr const& bufferID) const
|
2011-09-04 01:54:36 +02:00
|
|
|
|
{
|
2011-11-20 01:35:52 +01:00
|
|
|
|
return meta_->isLocked (bufferID);
|
2011-09-04 01:54:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffDescr
|
2011-09-21 02:23:12 +02:00
|
|
|
|
BufferProvider::getDescriptorFor (size_t storageSize)
|
2011-09-04 01:54:36 +02:00
|
|
|
|
{
|
2024-07-15 18:52:59 +02:00
|
|
|
|
return BuffDescr (*this, meta_->key (storageSize));
|
2011-09-04 01:54:36 +02:00
|
|
|
|
}
|
2011-11-12 00:36:53 +01:00
|
|
|
|
|
|
|
|
|
|
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffDescr
|
2011-11-12 00:36:53 +01:00
|
|
|
|
BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment)
|
|
|
|
|
|
{
|
2024-07-15 18:52:59 +02:00
|
|
|
|
return BuffDescr (*this, meta_->key (storageSize, specialTreatment));
|
2011-11-12 00:36:53 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-18 01:23:50 +01:00
|
|
|
|
size_t
|
|
|
|
|
|
BufferProvider::getBufferSize (HashVal typeID) const
|
|
|
|
|
|
{
|
|
|
|
|
|
metadata::Key& typeKey = meta_->get (typeID);
|
|
|
|
|
|
return typeKey.storageSize();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-20 01:35:52 +01:00
|
|
|
|
/** callback from implementation to build and enrol a BufferHandle,
|
|
|
|
|
|
* to be returned to the client as result of the #lockBuffer call.
|
|
|
|
|
|
* Performs the necessary metadata state transition leading from an
|
|
|
|
|
|
* abstract buffer type to a metadata::Entry corresponding to an
|
2011-11-26 00:09:59 +01:00
|
|
|
|
* actual buffer, which is locked for exclusive use by one client.
|
2011-11-20 01:35:52 +01:00
|
|
|
|
*/
|
2011-11-13 04:20:14 +01:00
|
|
|
|
BuffHandle
|
2024-07-28 19:29:27 +02:00
|
|
|
|
BufferProvider::buildHandle (HashVal typeID, Buff* storage, LocalTag const& localTag)
|
2011-11-13 04:20:14 +01:00
|
|
|
|
{
|
|
|
|
|
|
metadata::Key& typeKey = meta_->get (typeID);
|
2024-07-27 17:17:02 +02:00
|
|
|
|
metadata::Entry& entry = meta_->markLocked(typeKey, storage, localTag);
|
2011-11-13 04:20:14 +01:00
|
|
|
|
|
2024-07-15 18:52:59 +02:00
|
|
|
|
return BuffHandle (BuffDescr(*this, entry), storage);
|
2011-11-13 04:20:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-14 01:43:29 +01:00
|
|
|
|
/** BufferProvider API: declare in advance the need for working buffers.
|
|
|
|
|
|
* This optional call allows client code to ensure the availability of the
|
|
|
|
|
|
* necessary working space, prior to starting the actual operations. The
|
|
|
|
|
|
* client may reasonably assume to get the actual number of buffers, as
|
|
|
|
|
|
* indicated by the return value. A provider may be able to handle
|
|
|
|
|
|
* various kinds of buffers (e.g. of differing size), which are
|
2024-07-15 18:52:59 +02:00
|
|
|
|
* distinguished by _the type embodied into_ the BuffDescr.
|
2011-11-14 01:43:29 +01:00
|
|
|
|
* @return maximum number of simultaneously usable buffers of this type,
|
|
|
|
|
|
* to be retrieved later through calls to #lockBuffer.
|
|
|
|
|
|
* @throw error::State when no buffer of this kind can be provided
|
|
|
|
|
|
* @note the returned count may differ from the requested count.
|
|
|
|
|
|
*/
|
|
|
|
|
|
uint
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BufferProvider::announce (uint count, BuffDescr const& type)
|
2011-11-14 01:43:29 +01:00
|
|
|
|
{
|
|
|
|
|
|
uint actually_possible = prepareBuffers (count, type);
|
|
|
|
|
|
if (!actually_possible)
|
|
|
|
|
|
throw error::State ("unable to fulfil request for buffers"
|
|
|
|
|
|
,LUMIERA_ERROR_BUFFER_MANAGEMENT);
|
|
|
|
|
|
return actually_possible;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** BufferProvider API: retrieve a single buffer for exclusive use.
|
|
|
|
|
|
* This call actually claims a buffer of this type and marks it for
|
|
|
|
|
|
* use by client code. The returned handle allows for convenient access,
|
|
|
|
|
|
* but provides no automatic tracking or memory management. The client is
|
|
|
|
|
|
* explicitly responsible to invoke #releaseBuffer (which can be done directly
|
|
|
|
|
|
* on the BuffHandle).
|
|
|
|
|
|
* @return a copyable handle, representing this buffer and this usage transaction.
|
|
|
|
|
|
* @throw error::State when unable to provide this buffer
|
|
|
|
|
|
* @note this function may be used right away, without prior announcing, but then
|
|
|
|
|
|
* the client should be prepared for exceptions. The #announce operation allows
|
|
|
|
|
|
* to establish a reliably available baseline.
|
|
|
|
|
|
*/
|
|
|
|
|
|
BuffHandle
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BufferProvider::lockBuffer (BuffDescr const& type)
|
2011-11-14 01:43:29 +01:00
|
|
|
|
{
|
|
|
|
|
|
REQUIRE (was_created_by_this_provider (type));
|
|
|
|
|
|
|
|
|
|
|
|
return provideLockedBuffer (type);
|
|
|
|
|
|
} // is expected to call buildHandle() --> state transition
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** BufferProvider API: state transition to \em emitted state.
|
|
|
|
|
|
* Client code may signal a state transition through this optional operation.
|
|
|
|
|
|
* The actual meaning of an "emitted" buffer is implementation defined; similarly,
|
|
|
|
|
|
* some back-ends may actually do something when emitting a buffer (e.g. commit data
|
|
|
|
|
|
* to cache), while others just set a flag or do nothing at all. This state transition
|
|
|
|
|
|
* may be invoked at most once per locked buffer.
|
|
|
|
|
|
* @throw error::Fatal in case of invalid state transition sequence. Only a locked buffer
|
|
|
|
|
|
* may be emitted, and at most once.
|
|
|
|
|
|
* @warning by convention, emitting a buffer implies that the contained data is ready and
|
|
|
|
|
|
* might be used by other parts of the application.
|
2024-07-14 23:32:46 +02:00
|
|
|
|
* While an emitted buffer should not be modified anymore, it can still be accessed.
|
2011-11-14 01:43:29 +01:00
|
|
|
|
*/
|
|
|
|
|
|
void
|
2011-11-15 04:47:31 +01:00
|
|
|
|
BufferProvider::emitBuffer (BuffHandle const& handle)
|
2011-11-14 01:43:29 +01:00
|
|
|
|
{
|
2011-11-15 04:47:31 +01:00
|
|
|
|
metadata::Entry& metaEntry = meta_->get (handle.entryID());
|
2024-07-27 17:17:02 +02:00
|
|
|
|
mark_emitted (metaEntry.parentKey(), metaEntry.localTag());
|
2011-11-15 04:47:31 +01:00
|
|
|
|
metaEntry.mark(EMITTED);
|
2011-11-14 01:43:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** BufferProvider API: declare done and detach.
|
|
|
|
|
|
* Client code is required to release \em each previously locked buffer eventually.
|
|
|
|
|
|
* @warning invalidates the BuffHandle, clients mustn't access the buffer anymore.
|
|
|
|
|
|
* Right after releasing, an access through the handle will throw;
|
|
|
|
|
|
* yet the buffer might be re-used and the handle become valid
|
|
|
|
|
|
* later on accidentally.
|
|
|
|
|
|
* @note EX_FREE
|
|
|
|
|
|
*/
|
|
|
|
|
|
void
|
2011-11-15 04:47:31 +01:00
|
|
|
|
BufferProvider::releaseBuffer (BuffHandle const& handle)
|
|
|
|
|
|
try {
|
|
|
|
|
|
metadata::Entry& metaEntry = meta_->get (handle.entryID());
|
2011-11-26 00:09:59 +01:00
|
|
|
|
metaEntry.mark(FREE); // might invoke embedded dtor function
|
2024-07-28 19:29:27 +02:00
|
|
|
|
detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle);
|
2011-11-26 00:09:59 +01:00
|
|
|
|
meta_->release (metaEntry);
|
2011-11-14 01:43:29 +01:00
|
|
|
|
}
|
2011-11-15 04:47:31 +01:00
|
|
|
|
ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
|
2011-11-14 01:43:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
2011-11-25 20:23:31 +01:00
|
|
|
|
|
|
|
|
|
|
/** @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
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BufferProvider::attachTypeHandler (BuffHandle const& target, BuffDescr const& reference)
|
2011-11-25 20:23:31 +01:00
|
|
|
|
{
|
2011-11-26 00:09:59 +01:00
|
|
|
|
metadata::Entry& metaEntry = meta_->get (target.entryID());
|
|
|
|
|
|
metadata::Entry& refEntry = meta_->get (reference);
|
|
|
|
|
|
REQUIRE (refEntry.isTypeKey());
|
|
|
|
|
|
REQUIRE (!metaEntry.isTypeKey());
|
|
|
|
|
|
if (!metaEntry.isLocked())
|
2024-03-16 02:04:47 +01:00
|
|
|
|
throw error::Logic{"unable to attach an object because buffer isn't locked for use"
|
|
|
|
|
|
, LERR_(LIFECYCLE)};
|
2011-11-26 00:09:59 +01:00
|
|
|
|
|
|
|
|
|
|
metaEntry.useTypeHandlerFrom (refEntry); // EX_STRONG
|
2011-11-25 20:23:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @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)
|
2011-11-26 00:09:59 +01:00
|
|
|
|
try {
|
|
|
|
|
|
metadata::Entry& metaEntry = meta_->get (target.entryID());
|
|
|
|
|
|
metaEntry.invalidate (invokeDtor);
|
2024-07-28 19:29:27 +02:00
|
|
|
|
detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target);
|
2011-11-26 00:09:59 +01:00
|
|
|
|
meta_->release (metaEntry);
|
2011-11-25 20:23:31 +01:00
|
|
|
|
}
|
2011-11-26 00:09:59 +01:00
|
|
|
|
ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error")
|
|
|
|
|
|
|
2011-11-25 20:23:31 +01:00
|
|
|
|
|
|
|
|
|
|
|
2011-11-13 04:20:14 +01:00
|
|
|
|
bool
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BufferProvider::was_created_by_this_provider (BuffDescr const& descr) const
|
2011-11-13 04:20:14 +01:00
|
|
|
|
{
|
2024-11-14 22:10:43 +01:00
|
|
|
|
return isSameAdr (this, descr.provider_);
|
2011-11-13 04:20:14 +01:00
|
|
|
|
}
|
2011-11-26 00:09:59 +01:00
|
|
|
|
|
2011-11-13 04:20:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
2011-09-04 01:54:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
2024-07-15 18:52:59 +02:00
|
|
|
|
/* === BuffDescr and BuffHandle === */
|
2011-09-04 01:54:36 +02:00
|
|
|
|
|
|
|
|
|
|
bool
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffDescr::verifyValidity() const
|
2011-09-04 01:54:36 +02:00
|
|
|
|
{
|
2024-07-11 23:35:05 +02:00
|
|
|
|
ENSURE (provider_);
|
2011-09-17 18:25:45 +02:00
|
|
|
|
return provider_->verifyValidity(*this);
|
2011-09-04 01:54:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-09-19 01:42:37 +02:00
|
|
|
|
|
2011-11-21 02:28:44 +01:00
|
|
|
|
size_t
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffDescr::determineBufferSize() const
|
2011-11-21 02:28:44 +01:00
|
|
|
|
{
|
2024-07-11 23:35:05 +02:00
|
|
|
|
ENSURE (provider_);
|
2011-11-21 02:28:44 +01:00
|
|
|
|
return provider_->getBufferSize (*this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-07-11 23:35:05 +02:00
|
|
|
|
uint
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffDescr::announce (uint count)
|
2024-07-11 23:35:05 +02:00
|
|
|
|
{
|
|
|
|
|
|
ENSURE (provider_);
|
|
|
|
|
|
return provider_->announce(count, *this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BuffHandle
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffDescr::lockBuffer()
|
2024-07-11 23:35:05 +02:00
|
|
|
|
{
|
|
|
|
|
|
ENSURE (provider_);
|
|
|
|
|
|
return provider_->lockBuffer(*this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-14 01:43:29 +01:00
|
|
|
|
void
|
2011-11-25 18:20:01 +01:00
|
|
|
|
BuffHandle::emit()
|
2011-11-14 01:43:29 +01:00
|
|
|
|
{
|
2011-11-25 18:20:01 +01:00
|
|
|
|
REQUIRE (isValid());
|
|
|
|
|
|
descriptor_.provider_->emitBuffer(*this);
|
2011-11-14 01:43:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-09-19 01:42:37 +02:00
|
|
|
|
void
|
2011-11-25 18:20:01 +01:00
|
|
|
|
BuffHandle::release()
|
2011-09-19 01:42:37 +02:00
|
|
|
|
{
|
2011-11-25 18:20:01 +01:00
|
|
|
|
if (pBuffer_)
|
|
|
|
|
|
{
|
|
|
|
|
|
REQUIRE (isValid());
|
|
|
|
|
|
descriptor_.provider_->releaseBuffer(*this);
|
|
|
|
|
|
pBuffer_ = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
ENSURE (!isValid());
|
2011-09-19 01:42:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-11-20 01:35:52 +01:00
|
|
|
|
|
2011-11-25 20:23:31 +01:00
|
|
|
|
void
|
|
|
|
|
|
BuffHandle::emergencyCleanup()
|
|
|
|
|
|
{
|
2011-11-26 00:09:59 +01:00
|
|
|
|
descriptor_.provider_->emergencyCleanup(*this); // EX_FREE
|
|
|
|
|
|
pBuffer_ = 0;
|
2011-11-25 20:23:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-11-26 00:09:59 +01:00
|
|
|
|
/** Install a standard TypeHandler for an already locked buffer.
|
|
|
|
|
|
* This causes the dtor function to be invoked when releasing this buffer.
|
|
|
|
|
|
* The assumption is that client code will placement-construct an object
|
|
|
|
|
|
* into this buffer right away, and thus we're taking ownership on that object.
|
2024-07-15 18:52:59 +02:00
|
|
|
|
* @param type a reference BuffDescr defining an embedded TypeHandler to use
|
2011-11-26 00:09:59 +01:00
|
|
|
|
* A copy of this TypeHandler will be stored into the local metadata for
|
|
|
|
|
|
* this buffer only, not altering the basic buffer type in any way
|
|
|
|
|
|
* @throw lifecycle error when attempting to treat an buffer not in locked state
|
|
|
|
|
|
* @throw error::Logic in case of insufficient buffer space to hold the
|
|
|
|
|
|
* intended target object
|
|
|
|
|
|
* @note EX_STRONG
|
|
|
|
|
|
*/
|
2011-11-25 20:23:31 +01:00
|
|
|
|
void
|
2024-07-15 18:52:59 +02:00
|
|
|
|
BuffHandle::takeOwnershipFor(BuffDescr const& type)
|
2011-11-25 20:23:31 +01:00
|
|
|
|
{
|
2011-11-26 00:09:59 +01:00
|
|
|
|
if (!this->isValid())
|
2018-04-02 01:48:51 +02:00
|
|
|
|
throw error::Logic ("attaching an object requires an buffer in locked state", LERR_(LIFECYCLE));
|
2011-11-25 20:23:31 +01:00
|
|
|
|
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
|
|
|
|
|
|
}
|
2011-11-26 00:09:59 +01:00
|
|
|
|
|
2011-11-25 20:23:31 +01:00
|
|
|
|
|
|
|
|
|
|
|
2011-11-20 01:35:52 +01:00
|
|
|
|
|
2011-12-02 16:10:03 +01:00
|
|
|
|
}} // namespace engine
|