Lumiera  0.pre.03
»edit your freedom«
buffer-provider.cpp
Go to the documentation of this file.
1 /*
2  BufferProvider - Abstraction for Buffer management during playback/render
3 
4  Copyright (C)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
20 #include "lib/error.hpp"
23 #include "lib/util.hpp"
24 
25 using util::isSameAdr;
26 
27 namespace steam {
28 namespace engine {
29 
30  // storage for the default-marker constants
31  const TypeHandler TypeHandler::RAW{};
32  const LocalTag LocalTag::UNKNOWN{};
33 
34 
35  namespace { // impl. details and definitions
36 
37  const uint DEFAULT_DESCRIPTOR = 0;
38 
39  }
40 
41  LUMIERA_ERROR_DEFINE (BUFFER_MANAGEMENT, "Problem providing working buffers");
42 
43 
50  : meta_(new BufferMetadata (implementationID))
51  { }
52 
54 
55 
60  bool
61  BufferProvider::verifyValidity (BuffDescr const& bufferID) const
62  {
63  return meta_->isLocked (bufferID);
64  }
65 
66 
67  BuffDescr
68  BufferProvider::getDescriptorFor (size_t storageSize)
69  {
70  return BuffDescr (*this, meta_->key (storageSize));
71  }
72 
73 
74  BuffDescr
75  BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment)
76  {
77  return BuffDescr (*this, meta_->key (storageSize, specialTreatment));
78  }
79 
80 
81  size_t
82  BufferProvider::getBufferSize (HashVal typeID) const
83  {
84  metadata::Key& typeKey = meta_->get (typeID);
85  return typeKey.storageSize();
86  }
87 
88 
96  BufferProvider::buildHandle (HashVal typeID, Buff* storage, LocalTag const& localTag)
97  {
98  metadata::Key& typeKey = meta_->get (typeID);
99  metadata::Entry& entry = meta_->markLocked(typeKey, storage, localTag);
100 
101  return BuffHandle (BuffDescr(*this, entry), storage);
102  }
103 
104 
117  uint
118  BufferProvider::announce (uint count, BuffDescr const& type)
119  {
120  uint actually_possible = prepareBuffers (count, type);
121  if (!actually_possible)
122  throw error::State ("unable to fulfil request for buffers"
123  ,LUMIERA_ERROR_BUFFER_MANAGEMENT);
124  return actually_possible;
125  }
126 
127 
140  BuffHandle
142  {
143  REQUIRE (was_created_by_this_provider (type));
144 
145  return provideLockedBuffer (type);
146  } // is expected to call buildHandle() --> state transition
147 
148 
161  void
163  {
164  metadata::Entry& metaEntry = meta_->get (handle.entryID());
165  mark_emitted (metaEntry.parentKey(), metaEntry.localTag());
166  metaEntry.mark(EMITTED);
167  }
168 
169 
178  void
180  try {
181  metadata::Entry& metaEntry = meta_->get (handle.entryID());
182  metaEntry.mark(FREE); // might invoke embedded dtor function
183  detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle);
184  meta_->release (metaEntry);
185  }
186  ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
187 
188 
189 
190 
200  void
201  BufferProvider::attachTypeHandler (BuffHandle const& target, BuffDescr const& reference)
202  {
203  metadata::Entry& metaEntry = meta_->get (target.entryID());
204  metadata::Entry& refEntry = meta_->get (reference);
205  REQUIRE (refEntry.isTypeKey());
206  REQUIRE (!metaEntry.isTypeKey());
207  if (!metaEntry.isLocked())
208  throw error::Logic{"unable to attach an object because buffer isn't locked for use"
209  , LERR_(LIFECYCLE)};
210 
211  metaEntry.useTypeHandlerFrom (refEntry); // EX_STRONG
212  }
213 
214 
222  void
223  BufferProvider::emergencyCleanup (BuffHandle const& target, bool invokeDtor)
224  try {
225  metadata::Entry& metaEntry = meta_->get (target.entryID());
226  metaEntry.invalidate (invokeDtor);
227  detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target);
228  meta_->release (metaEntry);
229  }
230  ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error")
231 
232 
233 
234  bool
235  BufferProvider::was_created_by_this_provider (BuffDescr const& descr) const
236  {
237  return isSameAdr (this, descr.provider_);
238  }
239 
240 
241 
242 
243 
244  /* === BuffDescr and BuffHandle === */
245 
246  bool
247  BuffDescr::verifyValidity() const
248  {
249  ENSURE (provider_);
250  return provider_->verifyValidity(*this);
251  }
252 
253 
254  size_t
255  BuffDescr::determineBufferSize() const
256  {
257  ENSURE (provider_);
258  return provider_->getBufferSize (*this);
259  }
260 
261 
262  uint
263  BuffDescr::announce (uint count)
264  {
265  ENSURE (provider_);
266  return provider_->announce(count, *this);
267  }
268 
269 
270  BuffHandle
271  BuffDescr::lockBuffer()
272  {
273  ENSURE (provider_);
274  return provider_->lockBuffer(*this);
275  }
276 
277 
278  void
279  BuffHandle::emit()
280  {
281  REQUIRE (isValid());
282  descriptor_.provider_->emitBuffer(*this);
283  }
284 
285 
286  void
287  BuffHandle::release()
288  {
289  if (pBuffer_)
290  {
291  REQUIRE (isValid());
292  descriptor_.provider_->releaseBuffer(*this);
293  pBuffer_ = 0;
294  }
295  ENSURE (!isValid());
296  }
297 
298 
299  void
300  BuffHandle::emergencyCleanup()
301  {
302  descriptor_.provider_->emergencyCleanup(*this); // EX_FREE
303  pBuffer_ = 0;
304  }
305 
306 
319  void
321  {
322  if (!this->isValid())
323  throw error::Logic ("attaching an object requires an buffer in locked state", LERR_(LIFECYCLE));
324  if (this->size() < type.determineBufferSize())
325  throw error::Logic ("insufficient buffer size to hold an instance of that type");
326 
327  descriptor_.provider_->attachTypeHandler(*this, type); // EX_STRONG
328  }
329 
330 
331 
332 
333 }} // namespace engine
allocated buffer, no longer in use
bool verifyValidity(BuffDescr const &) const
uint announce(uint count, BuffDescr const &)
BufferProvider API: declare in advance the need for working buffers.
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Definition: error.hpp:266
void attachTypeHandler(BuffHandle const &target, BuffDescr const &reference)
allow for attaching and owing an object within an already created buffer
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
void releaseBuffer(BuffHandle const &)
BufferProvider API: declare done and detach.
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
bool isTypeKey() const
is this Entry just an (abstract) placeholder for a type?
void emergencyCleanup(BuffHandle const &target, bool invokeDtor=false)
An opaque descriptor to identify the type and further properties of a data buffer.
Definition: buffhandle.hpp:77
an opaque mark to be used by the BufferProvider implementation.
allocated buffer, returned from client
Entry & mark(BufferState newState)
Buffer state machine.
Steam-Layer implementation namespace root.
BuffDescr getDescriptorFor(size_t storageSize=0)
describe the kind of buffer managed by this provider
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Metadata for managing and accessing buffers.
Description of a Buffer-"type".
uint announce(uint count)
convenience shortcut to start a buffer handling cycle
static const TypeHandler RAW
Marker for the default case: raw buffer without type handling.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
BuffHandle lockBuffer(BuffDescr const &)
BufferProvider API: retrieve a single buffer for exclusive use.
bool isLocked() const
is this Entry currently associated to a concrete buffer? Is this buffer in use?
BufferProvider(Literal implementationID)
build a new provider instance, managing a family of buffers.
Lumiera error handling (C++ interface).
static const LocalTag UNKNOWN
Marker when no distinct local key is given.
Handle for a buffer for processing data, abstracting away the actual implementation.
Definition: buffhandle.hpp:111
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
virtual ~BufferProvider()
this is an ABC
A pair of functors to maintain a datastructure within a buffer.
BuffHandle buildHandle(HashVal typeID, Buff *storage, LocalTag const &=LocalTag::UNKNOWN)
callback from implementation to build and enrol a BufferHandle, to be returned to the client as resul...
bool isSameAdr(A const &a, B const &b)
compare plain object address identity, disregarding type.
Definition: util.hpp:411
void emitBuffer(BuffHandle const &)
BufferProvider API: state transition to emitted state.
Registry for managing buffer metadata.
placeholder type for the contents of a data buffer.
Definition: streamtype.hpp:112
A complete metadata Entry, based on a Key.
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition: error.h:71
Abstraction to represent buffer management and lifecycle within the render engine.