From e435822de63b23324da0c2f2fe4609984a3dcb57 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 8 Feb 2009 01:31:01 +0100 Subject: [PATCH] Ouch.. boost::ptr_vector depends on boost-serialisation. Write a simple replacement... --- src/lib/scoped-ptrvect.hpp | 162 ++++++++++++++++++++++++++++++ src/lib/scopedholder.hpp | 7 +- tests/40components.tests | 5 + tests/lib/scoped-ptrvect-test.cpp | 109 ++++++++++++++++++++ 4 files changed, 280 insertions(+), 3 deletions(-) create mode 100644 src/lib/scoped-ptrvect.hpp create mode 100644 tests/lib/scoped-ptrvect-test.cpp diff --git a/src/lib/scoped-ptrvect.hpp b/src/lib/scoped-ptrvect.hpp new file mode 100644 index 000000000..af48dac45 --- /dev/null +++ b/src/lib/scoped-ptrvect.hpp @@ -0,0 +1,162 @@ +/* + SCOPED-PTRVECT.hpp - simple noncopyable lifecycle managing collection of pointers + + Copyright (C) Lumiera.org + 2009, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file scoped-ptrvect.hpp + ** Managing lifecycle for a collection of objects. Sometimes we need to + ** build and own a number of objects, including lifecycle management. + ** For example, a service provider may need to maintain a number of individual + ** process handles. The solution here is deliberately kept simple, it is + ** similar to using a stl container with shared_ptr(s), but behaves rather + ** like boost::scoped_ptr. It provides the same basic functionality as + ** boost::ptr_vector, but doesn't require us to depend on boost-serialisation. + ** + ** Some details to note: + ** - contained objects accessed by reference, never NULL. + ** - TODO: iterators, detaching of objects... + ** - TODO: retro-fit with refarray interface (--> builder branch) + ** + ** @see scoped-ptrvect-test.cpp + ** @see scopedholder.hpp + ** @see gui::DisplayService usage example + */ + + +#ifndef LIB_SCOPED_PTRVECT_H +#define LIB_SCOPED_PTRVECT_H + + +#include "include/logging.h" +#include "lib/error.hpp" +#include "lib/util.hpp" + +#include +#include + + +namespace lib { + + using util::for_each; + + + + /** + * Simple vector based collection of pointers, noncopyable and managing + * lifecycle of the pointed-to objects. Implemented by a vector of + * bare pointers (private inheritance) + */ + template + class ScopedPtrVect + : std::vector, + boost::noncopyable + { + typedef std::vector _Vec; + + public: + typedef size_t size_type; + typedef T & reference; + typedef T const& const_reference; + + + ScopedPtrVect () + : _Vec() + { } + + explicit + ScopedPtrVect (size_type capacity) + : _Vec() + { + _Vec::reserve (capacity); + } + + ~ScopedPtrVect () + { + clear(); + } + + + /** take ownership of the given object, + * adding it at the end of the collection + * @note object is deleted in case of any + * problem while adding it + */ + T& + manage (T* obj) + { + if (obj) + try + { + push_back (obj); + return *obj; + } + catch(...) + { + delete obj; + throw; + } } + + + void + clear() + { + typedef typename _Vec::iterator VIter; + VIter e = this->end(); + for (VIter i = this->begin(); i!=e; ++i) + { + if (*i) + try + { + delete *i; + *i = 0; + } + catch(std::exception& ex) + { + WARN (library, "Problem while deallocating ScopedPtrVect: %s", ex.what()); + } } + _Vec::clear(); + } + + + /* ====== proxied vector functions ==================== */ + + size_type size () const { return _Vec::size(); } + size_type max_size () const { return _Vec::max_size(); } + size_type capacity () const { return _Vec::capacity(); } + bool empty () const { return _Vec::empty(); } + + + private: + /** currently not used as of 2/2009 */ + T* get(size_type i) + { + T* p (_Vec::at (i)); + if (!p) + throw lumiera::error::Invalid("no valid object at this index"); + else + return p; + } + }; + + + + +} // namespace lib +#endif diff --git a/src/lib/scopedholder.hpp b/src/lib/scopedholder.hpp index 6dbb8c37a..042c78844 100644 --- a/src/lib/scopedholder.hpp +++ b/src/lib/scopedholder.hpp @@ -25,9 +25,9 @@ ** Working with collections of objects, especially in conjunction with ** polymorphism, can be challenging when we are bound to care for lifecycle ** and ownership for the contained classes. There are several solutions, - ** including the boost::ptr_container library, the use of shared_ptr - ** or even a garbage collector. Sometimes the circumstances rather call - ** for a very simple or lightweight solution though. + ** including the boost::ptr_container library or lib::ScopedPtrVect, the + ** use of shared_ptr or even a garbage collector. Sometimes circumstances + ** rather call for a very simple or lightweight solution though. ** ** ScopedPtrHolder is a simple extension to boost::scoped_ptr, enabling ** to use it within STL containers if we stick to a specific protocol. @@ -49,6 +49,7 @@ ** @see scopedholdertest.cpp ** @see scopedholdertransfer.hpp use in std::vector ** @see AllocationCluster usage example + ** @see scoped-ptrvect.hpp simple pointer-holding collection */ diff --git a/tests/40components.tests b/tests/40components.tests index ba14f909f..d05bea6f9 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -295,6 +295,11 @@ out: .throw some exceptions... END +TEST "ScopedPtrVect_test" ScopedPtrVect_test < + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + + +#include "lib/test/run.hpp" +#include "lib/util.hpp" + +#include "lib/scoped-ptrvect.hpp" +#include "testdummy.hpp" + +#include +//#include + + +namespace lib { + namespace test { + + using ::Test; + using util::isnil; + +// using std::map; + using std::cout; + + typedef ScopedPtrVect VectD; + + + /******************************************************************** + * @test ScopedPtrVect manages the lifecycle of a number of objects. + */ + class ScopedPtrVect_test : public Test + { + + virtual void + run (Arg) + { + simpleUsage(); +// iterating(); +// detaching(); + } + + + + void + simpleUsage() + { + ASSERT (0==checksum); + { + VectD holder; + ASSERT (isnil (holder)); + ASSERT (0==checksum); + + Dummy* ptr = new Dummy(); + Dummy& ref = holder.manage (ptr); + ASSERT (!isnil (holder)); + ASSERT (0!=checksum); + ASSERT (&ref==ptr); + + holder.manage (new Dummy); + holder.manage (new Dummy); + ASSERT (3 == holder.size()); + + holder.clear(); + ASSERT (0==checksum); + ASSERT (isnil (holder)); + + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + holder.manage (new Dummy); + ASSERT (9 == holder.size()); + ASSERT (0!=checksum); + } + ASSERT (0==checksum); + } + + }; + + LAUNCHER (ScopedPtrVect_test, "unit common"); + + + }// namespace test + +} // namespace lib +