From 6c01579a26e395f1d2b4b727e051570169977edd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 2 Jan 2012 06:11:27 +0100 Subject: [PATCH] WIP draft implementation of ScopedCollection --- src/lib/error.hpp | 1 + src/lib/exception.cpp | 1 + src/lib/scoped-collection.hpp | 263 ++++++++++++++++++++++----- tests/lib/scoped-collection-test.cpp | 2 +- 4 files changed, 218 insertions(+), 49 deletions(-) diff --git a/src/lib/error.hpp b/src/lib/error.hpp index 110ffe61b..1677557be 100644 --- a/src/lib/error.hpp +++ b/src/lib/error.hpp @@ -125,6 +125,7 @@ namespace lumiera { LUMIERA_ERROR_DECLARE (LIFECYCLE); ///< Lifecycle assumptions violated LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached + LUMIERA_ERROR_DECLARE (INDEX_BOUNDS); ///< index out of bounds LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value LUMIERA_ERROR_DECLARE (UNCONNECTED); ///< missing connection LUMIERA_ERROR_DECLARE (UNIMPLEMENTED);///< unimplemented feature diff --git a/src/lib/exception.cpp b/src/lib/exception.cpp index 8c524e5d4..26ddaadb2 100644 --- a/src/lib/exception.cpp +++ b/src/lib/exception.cpp @@ -82,6 +82,7 @@ namespace lumiera { LUMIERA_ERROR_DEFINE (LIFECYCLE, "Lifecycle assumptions violated"); LUMIERA_ERROR_DEFINE (WRONG_TYPE, "runtime type mismatch"); LUMIERA_ERROR_DEFINE (ITER_EXHAUST, "end of sequence reached"); + LUMIERA_ERROR_DEFINE (INDEX_BOUNDS, "index out of bounds"); LUMIERA_ERROR_DEFINE (BOTTOM_VALUE, "invalid or NIL value"); LUMIERA_ERROR_DEFINE (UNCONNECTED, "missing connection"); LUMIERA_ERROR_DEFINE (UNIMPLEMENTED, "using a feature not yet implemented...."); diff --git a/src/lib/scoped-collection.hpp b/src/lib/scoped-collection.hpp index 8a2fb81e0..f0f8aac34 100644 --- a/src/lib/scoped-collection.hpp +++ b/src/lib/scoped-collection.hpp @@ -41,117 +41,284 @@ //#include "include/logging.h" -//#include "lib/iter-adapter.hpp" +#include "lib/iter-adapter.hpp" #include "lib/error.hpp" //#include "lib/util.hpp" //#include //#include #include +#include +#include namespace lib { + namespace error = lumiera::error; + using error::LUMIERA_ERROR_INDEX_BOUNDS; + /** * A fixed collection of noncopyable polymorphic objects. + * All child objects reside in a common chunk of storage * and are owned and managed by this collection holder. * Array style access and iteration. */ - template + template + < class I ///< the nominal Base/Interface class for a family of types + , size_t siz = sizeof(I) ///< maximum storage required for the targets to be held inline + > class ScopedCollection : boost::noncopyable { + + /** + * Wrapper to hold one Child object. + * The storage will be an heap allocated + * array of such Wrapper objects. + */ + class ElementHolder + : boost::noncopyable + { + + mutable char buf_[siz]; + + public: + ElementHolder () { } + ~ElementHolder () + { + destroy(); + } + + I& + accessObj() const + { + return reinterpret_cast (buf_); + } + + void + destroy() + { + accessObj().~I(); + } + + I& + operator* () const + { + return accessObj(); + } + + + + /** Abbreviation for placement new */ +#define EMBEDDED_ELEMENT_CTOR(_CTOR_CALL_) \ + BOOST_STATIC_ASSERT (siz >= sizeof(TY));\ + return *new(&buf_) _CTOR_CALL_; \ + + + template + TY& + create () + { + EMBEDDED_ELEMENT_CTOR ( TY() ) + } + + + template + TY& //___________________________________________ + create (A1& a1) ///< place object of type TY, using 1-arg ctor + { + EMBEDDED_ELEMENT_CTOR ( TY(a1) ) + } + + + template< class TY + , typename A1 + , typename A2 + > + TY& //___________________________________________ + create (A1& a1, A2& a2) ///< place object of type TY, using 2-arg ctor + { + EMBEDDED_ELEMENT_CTOR ( TY(a1,a2) ) + } + + + template< class TY + , typename A1 + , typename A2 + , typename A3 + > + TY& //___________________________________________ + create (A1& a1, A2& a2, A3& a3) ///< place object of type TY, using 3-arg ctor + { + EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3) ) + } + + + template< class TY + , typename A1 + , typename A2 + , typename A3 + , typename A4 + > + TY& //___________________________________________ + create (A1& a1, A2& a2, A3& a3, A4& a4) ///< place object of type TY, using 4-arg ctor + { + EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3,a4) ) + } + + + template< class TY + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + > + TY& //___________________________________________ + create (A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) ///< place object of type TY, using 5-arg ctor + { + EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3,a4,a5) ) + } +#undef EMBEDDED_ELEMENT_CTOR + }; + + typedef boost::scoped_array ElementStorage; + + size_t level_; + size_t capacity_; + ElementStorage elements_; + // typedef std::vector _Vec; // typedef typename _Vec::iterator VIter; + typedef ElementHolder* StorageIter; // -// typedef RangeIter RIter; -// typedef PtrDerefIter IterType; -// -// typedef typename IterType::ConstIterType ConstIterType; -// typedef typename IterType::WrappedConstIterType RcIter; + typedef RangeIter RIter; + typedef PtrDerefIter IterType; + + typedef typename IterType::ConstIterType ConstIterType; + typedef typename IterType::WrappedConstIterType RcIter; public: - typedef size_t size_type; +// typedef size_t size_type; // typedef T & reference; // typedef T const& const_reference; - ScopedCollection () - { } - - explicit - ScopedCollection (size_type capacity) - { - UNIMPLEMENTED ("prepare scoped collection storage"); - } - ~ScopedCollection () { clear(); } + explicit + ScopedCollection (size_t maxElements) + : level_(0) + , capacity_(maxElements) + , elements_(new ElementHolder[maxElements]) + { } + + template + ScopedCollection (size_t maxElements, CTOR builder) + : level_(0) + , capacity_(maxElements) + , elements_(new ElementHolder[maxElements]) + { + UNIMPLEMENTED ("use the builder to populate the elements right away"); + } void clear() { - UNIMPLEMENTED ("drop all content objects"); + REQUIRE (level_ <= capacity_, "Storage corrupted"); + + while (level_) + { + --level_; + try { + elements_[level_].destroy(); + } + ERROR_LOG_AND_IGNORE (progress, "Clean-up of element in ScopedCollection") + } } + void + populate() + try { + while (level_ < capacity_) + { + elements_[level_].template create(); + ++level_; + } + } + catch(...) + { + WARN (progress, "Failure while populating ScopedCollection. " + "All elements will be discarded"); + clear(); + throw; + } + /* === Element access and iteration === */ - T& - operator[] (size_type i) + I& + operator[] (size_t index) { - return *get(i); + if (index < level_) + return elements_[index]; + + throw error::Logic ("Attempt to access not (yet) existing object in ScopedCollection" + , LUMIERA_ERROR_INDEX_BOUNDS); } -// typedef IterType iterator; -// typedef ConstIterType const_iterator; -// -// iterator begin() { return iterator (allPtrs()); } -// iterator end() { return iterator ( RIter() ); } -// const_iterator begin() const { return const_iterator::build_by_cast (allPtrs()); } -// const_iterator end() const { return const_iterator::nil(); } + typedef IterType iterator; + typedef ConstIterType const_iterator; + + iterator begin() { return iterator (allPtrs()); } + iterator end() { return iterator ( RIter() ); } + const_iterator begin() const { return const_iterator::build_by_cast (allPtrs()); } + const_iterator end() const { return const_iterator::nil(); } /* ====== proxied vector functions ==================== */ -// size_type size () const { return _Vec::size(); } + size_t size () const { return level_; } // size_type max_size () const { return _Vec::max_size(); } // size_type capacity () const { return _Vec::capacity(); } -// bool empty () const { return _Vec::empty(); } + bool empty () const { return 0 == level_; } private: - /** @internal element access, including range and null check */ - T* - get (size_type i) - { - UNIMPLEMENTED("raw element access"); - } +// /** @internal element access, including range and null check */ +// T* +// get (size_type i) +// { +// UNIMPLEMENTED("raw element access"); +// } -// /** @internal access sequence of all managed pointers */ -// RIter -// allPtrs () -// { -// return RIter (_Vec::begin(), _Vec::end()); -// } -// RIter -// allPtrs () const -// { -// _Vec& elements = util::unConst(*this); -// return RIter (elements.begin(), elements.end()); -// } + /** @internal access sequence of all managed pointers */ + RIter + allPtrs () + { + ElementHolder * storage_begin = elements_.get(); + ElementHolder * storage_end = storage_begin + capacity_; + + return RIter (storage_begin, storage_end); + } + RIter + allPtrs () const + { + ScopedCollection& elements = util::unConst(*this); + return RIter (elements.begin(), elements.end()); + } }; diff --git a/tests/lib/scoped-collection-test.cpp b/tests/lib/scoped-collection-test.cpp index f712c239e..29eddda2f 100644 --- a/tests/lib/scoped-collection-test.cpp +++ b/tests/lib/scoped-collection-test.cpp @@ -117,7 +117,7 @@ namespace test{ CHECK (5 == container.size()); CHECK (0 != Dummy::checksum()); - holder.clear(); + container.clear(); CHECK (isnil (container)); CHECK (0 == container.size()); CHECK (0 == Dummy::checksum());