Lumiera  0.pre.03
»edit your freedom«
scoped-collection.hpp
Go to the documentation of this file.
1 /*
2  SCOPED-COLLECTION.hpp - managing a fixed collection of noncopyable polymorphic objects
3 
4  Copyright (C)
5  2012, 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 
60 #ifndef LIB_SCOPED_COLLECTION_H
61 #define LIB_SCOPED_COLLECTION_H
62 
63 
64 #include "lib/error.hpp"
65 #include "lib/nocopy.hpp"
66 #include "lib/meta/trait.hpp"
67 #include "lib/iter-adapter.hpp"
68 
69 #include <cstddef>
70 #include <type_traits>
71 
72 
73 namespace lib {
74 
75  namespace error = lumiera::error;
76  using LERR_(INDEX_BOUNDS);
77  using LERR_(CAPACITY);
78 
79 
80 
90  template
91  < class I
92  , size_t siz = sizeof(I)
93  >
96  {
97 
98  public:
107  {
108  alignas(I) mutable
109  std::byte buf_[siz];
110 
111  public:
112 
113  I&
114  accessObj() const
115  {
116  return * std::launder (reinterpret_cast<I*> (&buf_));
117  }
118 
119  void
120  destroy()
121  {
122  accessObj().~I();
123  }
124 
125 
126 
127 
129  template<class TY, typename...ARGS>
130  TY&
131  create (ARGS&& ...args)
132  {
133  static_assert ( meta::is_Subclass<TY,I>()
134  && sizeof(TY) <= siz,
135  "ElementHolder buffer too small");
136 
137  return *new(&buf_) TY (std::forward<ARGS> (args)...);
138  }
139  };
140 
141 
142 
143 
144 
145 
146  ~ScopedCollection ()
147  {
148  clear();
149  }
150 
151  explicit
152  ScopedCollection (size_t maxElements)
153  : level_(0)
154  , capacity_(maxElements)
155  , elements_(new ElementHolder[maxElements])
156  { }
157 
165  template<class CTOR>
166  ScopedCollection (size_t maxElements, CTOR builder)
167  : level_(0)
168  , capacity_(maxElements)
169  , elements_(new ElementHolder[maxElements])
170  {
171  populate_by (builder);
172  }
173 
182  template<class TY>
183  ScopedCollection (size_t maxElements, void (TY::*builder) (ElementHolder&), TY * const instance)
184  : level_(0)
185  , capacity_(maxElements)
186  , elements_(new ElementHolder[maxElements])
187  {
188  populate_by (builder,instance);
189  }
190 
191  /* == some pre-defined Builders == */
192 
193  class FillAll;
194 
195  template<typename TY>
196  class FillWith;
197 
198  template<typename IT>
199  class PullFrom;
200 
201  template<typename IT>
202  static PullFrom<IT>
203  pull (IT iter)
204  {
205  return PullFrom<IT> (iter);
206  }
207 
208  void
209  clear()
210  {
211  REQUIRE (level_ <= capacity_, "Storage corrupted");
212 
213  while (level_)
214  {
215  --level_;
216  try {
217  elements_[level_].destroy();
218  }
219  ERROR_LOG_AND_IGNORE (progress, "Clean-up of element in ScopedCollection")
220  }
221  }
222 
224  void
226  try {
227  while (level_ < capacity_)
228  {
229  elements_[level_].template create<I>();
230  ++level_;
231  }
232  }
233  catch(...)
234  {
235  WARN (progress, "Failure while populating ScopedCollection. "
236  "All elements will be discarded");
237  clear();
238  throw;
239  }
240 
248  template<class CTOR>
249  void
250  populate_by (CTOR builder)
251  try {
252  while (level_ < capacity_)
253  {
254  ElementHolder& storageFrame (elements_[level_]);
255  builder (storageFrame);
256  ++level_;
257  } }
258  catch(...)
259  {
260  WARN (progress, "Failure while populating ScopedCollection. "
261  "All elements will be discarded");
262  clear();
263  throw;
264  }
265 
270  template<class TY>
271  void
272  populate_by (void (TY::*builder) (ElementHolder&), TY * const instance)
273  try {
274  while (level_ < capacity_)
275  {
276  ElementHolder& storageFrame (elements_[level_]);
277  (instance->*builder) (storageFrame);
278  ++level_;
279  } }
280  catch(...)
281  {
282  WARN (progress, "Failure while populating ScopedCollection. "
283  "All elements will be discarded");
284  clear();
285  throw;
286  }
287 
288 
289 
293  I&
295  {
296  return emplace<I>();
297  }
298 
299 
304  template<class TY =I, typename...ARGS>
305  TY&
306  emplace (ARGS&& ...args)
307  {
308  __ensureSufficientCapacity();
309  TY& newElm = elements_[level_].template create<TY>(std::forward<ARGS> (args)...);
310  ++level_;
311  return newElm;
312  }
313 
314 
315 
316  /* === Element access and iteration === */
317 
318  I&
319  operator[] (size_t index) const
320  {
321  if (index < level_)
322  return elements_[index].accessObj();
323 
324  throw error::Logic ("Attempt to access not (yet) existing object in ScopedCollection"
325  , LERR_(INDEX_BOUNDS));
326  }
327 
328 
329 
332 
333 
334  iterator begin() { return iterator (this, _access_begin()); }
335  const_iterator begin() const { return const_iterator (this, _access_begin()); }
336  iterator end () { return iterator(); }
337  const_iterator end () const { return const_iterator(); }
338 
339 
340  size_t size () const { return level_; }
341  size_t capacity () const { return capacity_; }
342  bool empty () const { return 0 == level_; }
343 
344 
345  // use in standard range for loops...
346  friend iterator begin (ScopedCollection& sco) { return sco.begin(); }
347  friend const iterator begin (ScopedCollection const& sco){ return sco.begin(); }
348  friend iterator end (ScopedCollection& sco) { return sco.end(); }
349  friend const iterator end (ScopedCollection const& sco){ return sco.end(); }
350 
351 
352  private:
353  /* ==== Storage: heap allocated array of element buffers ==== */
354 
355  typedef std::unique_ptr<ElementHolder[]> ElementStorage;
356 
357  size_t level_;
358  size_t capacity_;
359  ElementStorage elements_;
360 
361 
362 
363  void
364  __ensureSufficientCapacity()
365  {
366  if (level_ >= capacity_)
367  throw error::State ("ScopedCollection exceeding the initially defined capacity"
368  , LERR_(CAPACITY));
369  }
370 
371 
372  /* ==== internal callback API for the iterator ==== */
373 
378  friend void
379  iterNext (const ScopedCollection*, I* & pos)
380  {
381  ElementHolder* & storageLocation = reinterpret_cast<ElementHolder* &> (pos);
382  ++storageLocation;
383  }
384 
385  friend void
386  iterNext (const ScopedCollection*, const I* & pos)
387  {
388  const ElementHolder* & storageLocation = reinterpret_cast<const ElementHolder* &> (pos);
389  ++storageLocation;
390  }
391 
393  template<typename POS>
394  friend bool
395  checkPoint (const ScopedCollection* src, POS & pos)
396  {
397  REQUIRE (src);
398  if ((pos) && (pos < src->_access_end()))
399  return true;
400  else
401  {
402  pos = 0;
403  return false;
404  } }
405 
406 
407  I* _access_begin() const { return & elements_[0].accessObj(); }
408  I* _access_end() const { return & elements_[level_].accessObj(); }
409 
410  };
411 
412 
413 
414 
415  /* === Supplement: pre-defined element builders === */
416 
426  template<class I, size_t siz>
427  class ScopedCollection<I,siz>::FillAll
428  {
429  public:
430  void
431  operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
432  {
433  storage.template create<I>();
434  }
435  };
436 
437  template<class I, size_t siz>
438  template<typename TY>
439  class ScopedCollection<I,siz>::FillWith
440  {
441  public:
442  void
443  operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
444  {
445  storage.template create<TY>();
446  }
447  };
448 
458  template<class I, size_t siz>
459  template<typename IT>
460  class ScopedCollection<I,siz>::PullFrom
461  {
462  IT iter_;
463 
464  using ElementType = typename meta::ValueTypeBinding<IT>::value_type;
465 
466  public:
467  PullFrom (IT source)
468  : iter_(source)
469  { }
470 
471  void
472  operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
473  {
474  storage.template create<ElementType> (*iter_);
475  ++iter_;
476  }
477  };
478 
479 
480 
481 } // namespace lib
482 #endif
A fixed collection of non-copyable polymorphic objects.
TY & create(ARGS &&...args)
place object of type TY, forwarding ctor arguments
ScopedCollection(size_t maxElements, void(TY::*builder)(ElementHolder &), TY *const instance)
variation of RAII-style: using a builder function, which is a member of some object.
#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
Helper template(s) for creating Lumiera Forward Iterators.
Any copy and copy construction prohibited.
Definition: nocopy.hpp:37
TY & emplace(ARGS &&...args)
push new entry at the end of this container and build object of type TY in place there ...
Implementation namespace for support and library code.
void populate_by(CTOR builder)
init all elements at once, invoking a builder functor for each.
Storage Frame to hold one Child object.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Mix-Ins to allow or prohibit various degrees of copying and cloning.
ScopedCollection(size_t maxElements, CTOR builder)
creating a ScopedCollection in RAII-style: The embedded elements will be created immediately.
friend bool checkPoint(const ScopedCollection *src, POS &pos)
Iteration-logic: detect iteration end.
void populate()
init all elements default constructed
Helpers for type detection, type rewriting and metaprogramming.
Lumiera error handling (C++ interface).
void populate_by(void(TY::*builder)(ElementHolder &), TY *const instance)
variation of element initialisation, invoking a member function of some manager object for each colle...
static PullFrom< IT > pull(IT iter)
fills by copy-constructing values pulled from the iterator IT
fills the ScopedCollection with default constructed TY-instances
fills the ScopedCollection with default constructed I-instances
I & emplaceElement()
push a new element of default type to the end of this container
verify compliance to an interface by subtype check
Definition: trait.hpp:323
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
friend void iterNext(const ScopedCollection *, I *&pos)
Iteration-logic: switch to next position.