Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
tracking-heap-block-provider.cpp
Go to the documentation of this file.
1/*
2 TrackingHeapBlockProvider - plain heap allocating BufferProvider implementation for tests
3
4 Copyright (C)
5 2011, 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"
21#include "include/logging.h"
23#include "lib/util-foreach.hpp"
24
26
27#include <algorithm>
28#include <vector>
29
30using util::and_all;
31using std::vector;
33
34
35
36namespace steam {
37namespace engine {
38
39 namespace error = lumiera::error;
40
42
43
44 namespace { // implementation helpers...
45
46 inline Buff*
47 asBuffer(void* mem)
48 {// type tag to mark memory address as Buffer
49 return static_cast<Buff*> (mem);
50 }
51
52
53 using diagn::Block;
54
57 inline bool
58 identifyBlock (Block const& inQuestion, void* storage)
59 {
60 return storage == &inQuestion;
61 }
62
64 inline function<bool(Block const&)>
66 {
67 return bind (identifyBlock, _1, storage);
68 }
69
70 template<class VEC>
71 inline Block*
72 pick_Block_by_storage (VEC& vec, void* blockLocation)
73 {
74 typename VEC::iterator pos
75 = std::find_if (vec.begin(),vec.end()
77 if (pos!=vec.end())
78 return &(*pos);
79 else
80 return NULL;
81 }
82 }
83
84
85
86 namespace diagn {
87
89
102 {
106
107 public:
109 : maxAllocCount_(0) // unlimited by default
110 , memBlockSize_(0)
111 , blockList_{}
112 { }
113
114 void
115 initialise (size_t blockSize)
116 {
117 memBlockSize_ = blockSize;
118 }
119 // standard copy operations are valid, but will
120 // raise an runtime error, once BlockPool is initialised.
121
123 {
125 ERROR (test, "Block actively in use while shutting down BufferProvider "
126 "allocation pool. This might lead to Segfault and memory leaks.");
127 }
128
130 void
132 {
133 for (Block& block : blockList_)
134 block.markReleased();
135 }
136
137 uint
138 prepare_for (uint number_of_expected_buffers)
139 {
140 if (maxAllocCount_ &&
141 maxAllocCount_ < blockList_.size() + number_of_expected_buffers)
142 {
143 ASSERT (maxAllocCount_ >= blockList_.size());
144 return maxAllocCount_ - blockList_.size();
145 }
146 // currently no hard limit imposed
147 return number_of_expected_buffers;
148 }
149
150
151 Block&
153 {
154 return blockList_.manage (new Block(memBlockSize_));
155 }
156
157
158 Block*
159 find (void* blockLocation)
160 {
161 return pick_Block_by_storage (blockList_, blockLocation);
162 }
163
164
165 Block*
167 {
168 return blockList_.detach (allocatedBlock);
169 }
170
171
172 size_t
173 size() const
174 {
175 return blockList_.size();
176 }
177
178 bool
179 isValid() const
180 {
181 return not blockList_.empty();
182 }
183
184 explicit
185 operator bool() const
186 {
187 return isValid();
188 }
189
190 private:
191 bool
193 {
194 try {
195 return and_all (blockList_, is_in_sane_state);
196 }
197 ERROR_LOG_AND_IGNORE (test, "State verification of diagnostic BufferProvider allocation pool");
198 return true;
199 }
200
201
202 static bool
203 is_in_sane_state (Block const& block)
204 {
205 return not block.was_used() or block.was_closed();
206 }
207 };
208 }
209
210
211
212 namespace { // Details of allocation and accounting
213
214 const uint MAX_BUFFERS = 50;
215
217
218 } // (END) Details of allocation and accounting
219
220
221
226 : BufferProvider ("Diagnostic_HeapAllocated")
227 , pool_(new diagn::PoolTable)
228 , outSeq_()
229 { }
230
232 {
233 INFO (proc_mem, "discarding %zu diagnostic buffer entries", outSeq_.size());
234 }
235
236
237 /* ==== Implementation of the BufferProvider interface ==== */
238
239 uint
240 TrackingHeapBlockProvider::prepareBuffers(uint requestedAmount, HashVal typeID)
241 {
242 diagn::BlockPool& responsiblePool = getBlockPoolFor (typeID);
243 return responsiblePool.prepare_for (requestedAmount);
244 }
245
246
249 {
250 diagn::BlockPool& blocks = getBlockPoolFor (typeID);
251 diagn::Block& newBlock = blocks.createBlock();
252 return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock);
253 }
254
255
256 void
257 TrackingHeapBlockProvider::mark_emitted (HashVal typeID, LocalTag const& specifics)
258 {
259 diagn::Block* block4buffer = locateBlock (typeID, specifics);
260 if (!block4buffer)
261 throw error::Logic ("Attempt to emit a buffer not known to this BufferProvider"
262 , LUMIERA_ERROR_BUFFER_MANAGEMENT);
263 diagn::BlockPool& pool = getBlockPoolFor (typeID);
264 Block* active = pool.transferResponsibility (block4buffer);
265 if (active)
266 outSeq_.manage (active);
267 else
268 if (block4buffer->was_closed())
269 WARN (proc_mem, "Attempt to emit() an already closed buffer.");
270 else
271 WARN (proc_mem, "Attempt to emit() a buffer not found in active pool. "
272 "Maybe duplicate call to emit()?");
273 }
274
275
277 void
278 TrackingHeapBlockProvider::detachBuffer (HashVal typeID, LocalTag const& specifics, Buff& storage)
279 {
280 diagn::Block* block4buffer = locateBlock (typeID, specifics);
281 REQUIRE (block4buffer, "releasing a buffer not allocated through this provider");
282 REQUIRE (util::isSameAdr (storage, block4buffer->accessMemory()));
283 block4buffer->markReleased();
284 }
285
286
287
288 /* ==== Implementation details ==== */
289
290 size_t
292 {
293 return outSeq_.size();
294 }
295
296 void
298 {
299 for (auto& [_, blockPool] : *pool_)
300 blockPool.discard();
301 }
302
305 {
306 if (!withinOutputSequence (bufferID))
307 return emptyPlaceholder;
308 else
309 return outSeq_[bufferID];
310 }
311
312 bool
314 {
315 if (bufferID >= MAX_BUFFERS)
316 throw error::Fatal ("hardwired internal limit for test buffers exceeded");
317
318 return bufferID < outSeq_.size();
319 }
320
323 {
324 diagn::BlockPool& pool = (*pool_)[typeID];
325 if (!pool)
326 pool.initialise(getBufferSize(typeID));
327 return pool;
328 }
329
331 TrackingHeapBlockProvider::locateBlock (HashVal typeID, void* storage)
332 {
333 diagn::BlockPool& pool = getBlockPoolFor (typeID);
334 diagn::Block* block4buffer = pool.find (storage);
335 return block4buffer? block4buffer
336 : searchInOutSeqeuence (storage);
337 }
338
341 {
342 return pick_Block_by_storage (outSeq_, blockLocation);
343 }
344
345
346
347
348}} // namespace engine
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
size_type size() const
T * detach(void *objAddress)
withdraw responsibility for a specific object.
T & manage(T *obj)
take ownership of the given object, adding it at the end of the collection
placeholder type for the contents of a data buffer.
Handle for a buffer for processing data, abstracting away the actual implementation.
Interface: a facility providing and managing working buffers for media calculations.
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...
size_t getBufferSize(HashVal typeID) const
an opaque mark to be used by the BufferProvider implementation.
diagn::Block * locateBlock(HashVal typeID, void *)
virtual void mark_emitted(HashVal, LocalTag const &) override
virtual uint prepareBuffers(uint count, HashVal typeID) override
virtual BuffHandle provideLockedBuffer(HashVal typeID) override
virtual void detachBuffer(HashVal, LocalTag const &, Buff &) override
mark a buffer as officially discarded
void discard()
mark all managed blocks as disposed
static bool is_in_sane_state(Block const &block)
uint prepare_for(uint number_of_expected_buffers)
Block * transferResponsibility(Block *allocatedBlock)
Helper for implementing a diagnostic BufferProvider: A block of heap allocated storage,...
Lumiera error handling (C++ interface).
#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:267
#define _(String)
Definition gtk-base.hpp:68
unsigned int uint
Definition integral.hpp:29
return NULL
Definition llist.h:586
This header is for including and configuring NoBug.
LumieraError< LERR_(FATAL), Logic > Fatal
Definition error.hpp:208
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
function< bool(Block const &)> search_for_block_using_this_storage(void *storage)
build a searching predicate
bool identifyBlock(Block const &inQuestion, void *storage)
helper to find Block entries based on their raw memory address
Steam-Layer implementation namespace root.
Test runner and basic definitions for tests.
bool isSameAdr(A const &a, B const &b)
compare plain object address identity, disregarding type.
Definition util.hpp:411
bool and_all(IT i, IT end, FUN predicate)
All quantification: check if all elements of a collection satisfy the given predicate.
Managing lifecycle for a collection of objects.
Dummy implementation of the BufferProvider interface to support writing unit tests.
Perform operations "for each element" of a collection.