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) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
29 #include "lib/error.hpp"
32 #include "lib/util.hpp"
33 
34 using util::isSameObject;
35 
36 namespace steam {
37 namespace engine {
38 
39 
40  namespace { // impl. details and definitions
41 
42  const uint DEFAULT_DESCRIPTOR = 0;
43 
44  }
45 
46  LUMIERA_ERROR_DEFINE (BUFFER_MANAGEMENT, "Problem providing working buffers");
47 
48 
55  : meta_(new BufferMetadata (implementationID))
56  { }
57 
59 
60 
65  bool
67  {
68  return meta_->isLocked (bufferID);
69  }
70 
71 
73  BufferProvider::getDescriptorFor (size_t storageSize)
74  {
75  return BufferDescriptor (*this, meta_->key (storageSize));
76  }
77 
78 
80  BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment)
81  {
82  return BufferDescriptor (*this, meta_->key (storageSize, specialTreatment));
83  }
84 
85 
86  size_t
87  BufferProvider::getBufferSize (HashVal typeID) const
88  {
89  metadata::Key& typeKey = meta_->get (typeID);
90  return typeKey.storageSize();
91  }
92 
93 
100  BuffHandle
101  BufferProvider::buildHandle (HashVal typeID, void* storage, LocalKey const& implID)
102  {
103  metadata::Key& typeKey = meta_->get (typeID);
104  metadata::Entry& entry = meta_->markLocked(typeKey, storage, implID);
105 
106  return BuffHandle (BufferDescriptor(*this, entry), storage);
107  }
108 
109 
122  uint
123  BufferProvider::announce (uint count, BufferDescriptor const& type)
124  {
125  uint actually_possible = prepareBuffers (count, type);
126  if (!actually_possible)
127  throw error::State ("unable to fulfil request for buffers"
128  ,LUMIERA_ERROR_BUFFER_MANAGEMENT);
129  return actually_possible;
130  }
131 
132 
145  BuffHandle
147  {
148  REQUIRE (was_created_by_this_provider (type));
149 
150  return provideLockedBuffer (type);
151  } // is expected to call buildHandle() --> state transition
152 
153 
166  void
168  {
169  metadata::Entry& metaEntry = meta_->get (handle.entryID());
170  mark_emitted (metaEntry.parentKey(), metaEntry.localKey());
171  metaEntry.mark(EMITTED);
172  }
173 
174 
183  void
185  try {
186  metadata::Entry& metaEntry = meta_->get (handle.entryID());
187  metaEntry.mark(FREE); // might invoke embedded dtor function
188  detachBuffer (metaEntry.parentKey(), metaEntry.localKey());
189  meta_->release (metaEntry);
190  }
191  ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
192 
193 
194 
195 
205  void
207  {
208  metadata::Entry& metaEntry = meta_->get (target.entryID());
209  metadata::Entry& refEntry = meta_->get (reference);
210  REQUIRE (refEntry.isTypeKey());
211  REQUIRE (!metaEntry.isTypeKey());
212  if (!metaEntry.isLocked())
213  throw error::Logic{"unable to attach an object because buffer isn't locked for use"
214  , LERR_(LIFECYCLE)};
215 
216  metaEntry.useTypeHandlerFrom (refEntry); // EX_STRONG
217  }
218 
219 
227  void
228  BufferProvider::emergencyCleanup (BuffHandle const& target, bool invokeDtor)
229  try {
230  metadata::Entry& metaEntry = meta_->get (target.entryID());
231  metaEntry.invalidate (invokeDtor);
232  detachBuffer (metaEntry.parentKey(), metaEntry.localKey());
233  meta_->release (metaEntry);
234  }
235  ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error")
236 
237 
238 
239  bool
240  BufferProvider::was_created_by_this_provider (BufferDescriptor const& descr) const
241  {
242  return isSameObject (*this, *descr.provider_);
243  }
244 
245 
246 
247 
248 
249  /* === BufferDescriptor and BuffHandle === */
250 
251  bool
252  BufferDescriptor::verifyValidity() const
253  {
254  return provider_->verifyValidity(*this);
255  }
256 
257 
258  size_t
259  BufferDescriptor::determineBufferSize() const
260  {
261  return provider_->getBufferSize (*this);
262  }
263 
264 
265  void
266  BuffHandle::emit()
267  {
268  REQUIRE (isValid());
269  descriptor_.provider_->emitBuffer(*this);
270  }
271 
272 
273  void
274  BuffHandle::release()
275  {
276  if (pBuffer_)
277  {
278  REQUIRE (isValid());
279  descriptor_.provider_->releaseBuffer(*this);
280  pBuffer_ = 0;
281  }
282  ENSURE (!isValid());
283  }
284 
285 
286  void
287  BuffHandle::emergencyCleanup()
288  {
289  descriptor_.provider_->emergencyCleanup(*this); // EX_FREE
290  pBuffer_ = 0;
291  }
292 
293 
306  void
308  {
309  if (!this->isValid())
310  throw error::Logic ("attaching an object requires an buffer in locked state", LERR_(LIFECYCLE));
311  if (this->size() < type.determineBufferSize())
312  throw error::Logic ("insufficient buffer size to hold an instance of that type");
313 
314  descriptor_.provider_->attachTypeHandler(*this, type); // EX_STRONG
315  }
316 
317 
318 
319 
320 }} // namespace engine
allocated buffer, no longer in use
void attachTypeHandler(BuffHandle const &target, BufferDescriptor const &reference)
allow for attaching and owing an object within an already created buffer
#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:275
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:85
bool isTypeKey() const
is this Entry just an (abstract) placeholder for a type?
BuffHandle buildHandle(HashVal typeID, void *storage, LocalKey const &)
callback from implementation to build and enrol a BufferHandle, to be returned to the client as resul...
void emergencyCleanup(BuffHandle const &target, bool invokeDtor=false)
allocated buffer, returned from client
Entry & mark(BufferState newState)
Buffer state machine.
Steam-Layer implementation namespace root.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
an opaque ID to be used by the BufferProvider implementation.
uint announce(uint count, BufferDescriptor const &)
BufferProvider API: declare in advance the need for working buffers.
Metadata for managing and accessing buffers.
Description of a Buffer-"type".
BufferDescriptor getDescriptorFor(size_t storageSize=0)
describe the kind of buffer managed by this provider
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
An opaque descriptor to identify the type and further properties of a data buffer.
Definition: buffhandle.hpp:85
bool isLocked() const
is this Entry currently associated to a concrete buffer? Is this buffer in use?
BuffHandle lockBuffer(BufferDescriptor const &)
BufferProvider API: retrieve a single buffer for exclusive use.
BufferProvider(Literal implementationID)
build a new provider instance, managing a family of buffers.
Lumiera error handling (C++ interface).
Handle for a buffer for processing data, abstracting away the actual implementation.
Definition: buffhandle.hpp:115
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:56
virtual ~BufferProvider()
this is an ABC
A pair of functors to maintain a datastructure within a buffer.
bool verifyValidity(BufferDescriptor const &) const
void emitBuffer(BuffHandle const &)
BufferProvider API: state transition to emitted state.
Registry for managing buffer metadata.
A complete metadata Entry, based on a Key.
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition: error.h:80
Abstraction to represent buffer management and lifecycle within the render engine.
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372