Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
allocation-cluster.cpp
Go to the documentation of this file.
1 /*
2  AllocationCluster - allocating and owning a pile of objects
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 
33 #include "lib/error.hpp"
34 #include "lib/util.hpp"
35 #include "lib/sync.hpp"
36 
37 using util::isnil;
38 
39 
40 namespace lib {
41 
67  : public Sync<RecursiveLock_NoWait>
68  {
69  typedef std::vector<char*> MemTable;
71  MemTable mem_;
72  size_t top_;
73 
74  public:
75  MemoryManager(TypeInfo info) : top_(0) { reset(info); }
77 
78  size_t size() const;
79 
80  void purge();
81  void reset(TypeInfo info);
82 
83  void* allocate();
84 
85  void commit (void* pendingAlloc);
86 
87  private:
88  void clearStorage();
89  };
90 
91 
92 
97  size_t
99  {
100  return top_;
101  }
102 
103 
104  void
106  {
107  Lock sync(this);
108 
109  if (0 < mem_.size()) purge();
110  type_ = info;
111 
112  ENSURE (0==top_);
113  ENSURE (isnil (mem_));
114  ENSURE (0 < type_.allocSize);
115  ENSURE (type_.killIt);
116  }
117 
118 
119  void
121  {
122  Lock sync(this);
123 
124  REQUIRE (type_.killIt, "we need a deleter function");
125  REQUIRE (0 < type_.allocSize, "allocation size unknown");
126  REQUIRE (top_ == mem_.size() || (top_+1) == mem_.size());
127 
128  while (top_)
129  type_.killIt (mem_[--top_]);
130  clearStorage();
131  }// note: unnecessary to kill pending allocations
132 
133 
134  inline void
136  {
137  for (size_t i=mem_.size(); 0 < i; )
138  delete[] mem_[--i];
139  mem_.clear();
140  }
141 
142 
143  inline void*
145  {
146  Lock sync(this);
147 
148  REQUIRE (0 < type_.allocSize);
149  REQUIRE (top_ <= mem_.size());
150 
151  if (top_==mem_.size())
152  mem_.resize(top_+1);
153 
154  if (!mem_[top_]) // re-use existing allocation, if any
155  mem_[top_] = new char[type_.allocSize];
156 
157  ENSURE (top_ < mem_.size());
158  ENSURE (mem_[top_]);
159  return mem_[top_];
160  }
161 
162 
163  inline void
165  {
166  Lock sync(this);
167 
168  REQUIRE (pendingAlloc);
169  ASSERT (top_ < mem_.size());
170  ASSERT (pendingAlloc == mem_[top_], "allocation protocol violated");
171 
172  ++top_;
173 
174  ENSURE (top_ == mem_.size());
175  }
176 
177 
178 
181 
182 
188  {
189  TRACE (memory, "new AllocationCluster");
190  }
191 
192 
198  {
199  try
200  { // avoiding a per-instance lock for now.
201  ClassLock<AllocationCluster> guard; // (see note in the class description)
202 
203  TRACE (memory, "shutting down AllocationCluster");
204  for (size_t i = typeHandlers_.size(); 0 < i; --i)
205  if (handler(i))
206  handler(i)->purge();
207 
208  typeHandlers_.clear();
209 
210  }
211  catch (lumiera::Error & ex)
212  {
213  WARN (progress, "Exception while closing AllocationCluster: %s", ex.what());
214  }
215  catch (...)
216  {
217  ALERT (progress, "Unexpected fatal Exception while closing AllocationCluster.");
219  }
220  }
221 
222 
223 
224  void*
226  {
227  if (!slot || slot > typeHandlers_.size() || !handler(slot) )
228  return 0; // Memory manager not yet initialised
229  else
230  return handler(slot)->allocate();
231  }
232 
233 
234  void*
236  {
237  ASSERT (0 < slot);
238 
239  { // avoiding a per-instance lock for now.
240  ClassLock<AllocationCluster> guard; // (see note in the class description)
241 
242  if (slot > typeHandlers_.size())
243  typeHandlers_.resize(slot);
244  if (!handler(slot))
245  handler(slot).reset (new MemoryManager (type));
246 
247  }
248 
249  ASSERT (handler(slot));
250  return initiateAlloc(slot);
251  }
252 
253 
254  void
255  AllocationCluster::finishAlloc (size_t& slot, void* allocatedObj)
256  {
257  ASSERT (handler(slot));
258  ASSERT (allocatedObj);
259 
260  handler(slot)->commit(allocatedObj);
261  }
262 
263 
264  /* === diagnostics helpers === */
265 
268  size_t
270  {
271  size_t size(0);
272  typedef ManagerTable::const_iterator Iter;
273 
274  for (Iter ii= typeHandlers_.begin(); ii != typeHandlers_.end(); ++ii )
275  if (*ii)
276  size += (*ii)->size();
277 
278  return size;
279  }
280 
281 
282  size_t
284  {
285  if (handler (slot))
286  return handler(slot)->size();
287  else
288  return 0;
289  }
290 
291 
292 
293 
294 
295 
296 } // namespace lib
Facility for monitor object based locking.
Definition: sync.hpp:425
static size_t maxTypeIDs
storage for static bookkeeping of type allocation slots
HashVal slot(Query< asset::Pipe > const &query)
yield a suitable table slot for this query
void finishAlloc(size_t &slot, void *)
enrol the allocation after successful ctor call
size_t top_
index of the next slot available for allocation
Memory management for the low-level model (render nodes network).
Implementation namespace for support and library code.
void lumiera_unexpectedException() noexcept
global function for handling unknown exceptions encountered at functions declaring not to throw this ...
Object Monitor based synchronisation.
TRACE(test,"inserted %d", data)
size_t size() const
the top_ index always points at the next slot not yet holding a finished, committed allocation...
typename meta::Strip< CON >::TypeReferred::const_iterator const_iterator
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
HMemManager & handler(size_t slot)
void * initiateAlloc(size_t &slot)
implementation of the actual memory allocation is pushed down to the MemoryManager impl...
ManagerTable typeHandlers_
table of active MemoryManager instances
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
Lumiera error handling (C++ interface).
A synchronisation protection guard employing a lock scoped to the parameter type as a whole...
virtual CStr what() const noexceptoverride
std::exception interface : yield a diagnostic message
"Low-level" Memory manager for allocating small objects of a fixed size.
size_t countActiveInstances(size_t &slot) const
ENSURE(r==&pq)
Interface and Base definition for all Lumiera Exceptions.
Definition: error.hpp:69
~AllocationCluster()
On shutdown of the AllocationCluster we need to assure a certain destruction order is maintained by e...
AllocationCluster()
creating a new AllocationCluster prepares a table capable of holding the individual object families t...