diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/core/Managed.hpp | 191 | ||||
-rw-r--r-- | src/core/ManagedContainers.hpp | 111 | ||||
-rw-r--r-- | test/core/ManagedContainersTest.cpp | 80 | ||||
-rw-r--r-- | test/core/ManagedTest.cpp | 84 | ||||
-rw-r--r-- | test/core/TestManaged.hpp | 62 |
6 files changed, 214 insertions, 317 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e3d3c7..97ee48c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,7 +136,8 @@ IF(TEST) # Add all unit test files ADD_EXECUTABLE(ousia_test_core -# test/core/ManagedTest + test/core/ManagedTest + test/core/ManagedContainersTest test/core/NodeTest test/core/script/FunctionTest test/core/script/ObjectTest diff --git a/src/core/Managed.hpp b/src/core/Managed.hpp index 3386ff8..6199e33 100644 --- a/src/core/Managed.hpp +++ b/src/core/Managed.hpp @@ -737,197 +737,6 @@ public: Managed *getOwner() const { return owner; } }; -/** - * Template class which can be used to collect "Owned" refrences to a certain - * type of managed object. This class should be used in favour of other - * collections of handles, it takes care of acquiring an owned handle from the - * owner of this collection whenever a new element is added. - * - * @param T is the type of the Managed object that should be managed. - * @param Collection should be a stl container of Owned<T> - */ -template <class T, class Collection> -class ManagedCollection { -public: - using collection_type = Collection; - using value_type = typename collection_type::value_type; - using reference = typename collection_type::reference; - using const_reference = typename collection_type::const_reference; - using iterator = typename collection_type::iterator; - using const_iterator = typename collection_type::const_iterator; - using size_type = typename collection_type::size_type; - -private: - Handle<Managed> owner; - collection_type c; - -protected: - /** - * Function which can be overridden by child classes to execute special code - * whenever a new element is added to the collection. - */ - virtual void addManaged(Handle<T> h) {} - - /** - * Function which can be overriden by child classes to execute special code - * whenever an element is removed from the collection. - */ - virtual void deleteManaged(Handle<T> h) {} - -public: - /** - * Default constructor. - * - * @param owner is the managed object which owns the collection and all - * handles to other managed objects stored within. - */ - ManagedCollection(Handle<Managed> owner) : owner(owner){}; - - /** - * Initialize with an iterator from another collection. - * - * @param owner is the managed object which owns the collection and all - * handles to other managed objects stored within. - * @param first is an iterator pointing at the first element to be copied - * from some other collection. - * @param last is an iterator pointing at the last element to be copied - * from some other collection. - */ - template <class InputIterator> - ManagedCollection(Handle<Managed> owner, InputIterator first, - InputIterator last) - : owner(owner) - { - insert(c.begin, first, last); - } - - /** - * Initialize with another collection. - * - * @param owner is the managed object which owns the collection and all - * handles to other managed objects stored within. - * @param in is a reference at some other collection with content that - * should be copied. - */ - template <class InputCollection> - ManagedCollection(Handle<Managed> owner, const InputCollection &in) - : owner(owner) - { - for (const auto &e : in) { - push_back(e); - } - } - - /** - * Virtual destructor. - */ - virtual ~ManagedCollection(){}; - - /* State functions */ - size_type size() const noexcept { return c.size(); } - bool empty() const noexcept { return c.empty(); } - - /* Front and back */ - reference front() { return c.front(); } - const_reference front() const { return c.front(); } - reference back() { return c.back(); } - const_reference back() const { return c.back(); } - - /* Iterators */ - iterator begin() { return c.begin(); } - iterator end() { return c.end(); } - - iterator rbegin() { return c.rbegin(); } - iterator rend() { return c.rend(); } - - const_iterator begin() const { return c.cbegin(); } - const_iterator end() const { return c.cend(); } - - const_iterator cbegin() const { return c.cbegin(); } - const_iterator cend() const { return c.cend(); } - - const_iterator rbegin() const { return c.crbegin(); } - const_iterator rend() const { return c.crend(); } - - const_iterator crbegin() const { return c.crbegin(); } - const_iterator crend() const { return c.crend(); } - - /* Insert and delete operations */ - - iterator insert(const_iterator position, Handle<T> h) - { - Rooted<T> rooted{h}; - addManaged(rooted); - return c.insert(position, owner->acquire(h)); - } - - template <class InputIterator> - iterator insert(const_iterator position, InputIterator first, - InputIterator last) - { - for (InputIterator it = first; it != last; it++) { - position = insert(position, *it); - position++; - } - } - - iterator erase(iterator position) - { - deleteManaged(*position); - return c.erase(position); - } - - iterator erase(iterator first, iterator last) - { - for (const_iterator it = first; it != last; it++) { - deleteManaged(*it); - } - return c.erase(first, last); - } - - iterator find(const Handle<T> h) { - for (iterator it = begin(); it != end(); it++) { - if (*it == h) { - return it; - } - } - return end(); - } - - const_iterator find(const Handle<T> h) const { - for (const_iterator it = cbegin(); it != cend(); it++) { - if (*it == h) { - return it; - } - } - return cend(); - } - - void push_back(Handle<T> h) - { - Rooted<T> rooted{h}; - addManaged(rooted); - c.push_back(owner->acquire(rooted)); - } - - void pop_back() - { - if (!empty()) { - deleteElement(c.back()); - } - c.pop_back(); - } -}; - -/** - * Special type of ManagedCollection based on a STL vector. - */ -template<class T> -class ManagedVector : public ManagedCollection<T, std::vector<Owned<T>>> { -public: - using ManagedCollection<T, std::vector<Owned<T>>>::ManagedCollection; -}; - } #endif /* _OUSIA_MANAGED_HPP_ */ diff --git a/src/core/ManagedContainers.hpp b/src/core/ManagedContainers.hpp index c1787b4..9d3dc96 100644 --- a/src/core/ManagedContainers.hpp +++ b/src/core/ManagedContainers.hpp @@ -119,9 +119,19 @@ public: * @param Collection should be a STL list container of Owned<T> */ template <class T, class Collection> -class ManagedGenericList : public ManagedContainer() { +class ManagedGenericList : public ManagedContainer<T, Collection> { +private: + using Base = ManagedContainer<T, Collection>; + public: - using ManagedContainer<T, Collection>::ManagedContainer; + using Base::ManagedContainer; + using collection_type = typename Base::collection_type; + using value_type = typename Base::value_type; + using reference = typename Base::reference; + using const_reference = typename Base::const_reference; + using iterator = typename Base::iterator; + using const_iterator = typename Base::const_iterator; + using size_type = typename Base::size_type; /** * Initialize with an iterator from another collection. @@ -134,10 +144,11 @@ public: * from some other collection. */ template <class InputIterator> - ManagedGenericList(Handle<Managed> owner, InputIterator first, InputIterator last) + ManagedGenericList(Handle<Managed> owner, InputIterator first, + InputIterator last) : ManagedContainer<T, Collection>(owner) { - insert(c.begin(), first, last); + insert(Base::c.begin(), first, last); } /** @@ -158,29 +169,29 @@ public: } /* Front and back */ - reference front() { return c.front(); } - const_reference front() const { return c.front(); } - reference back() { return c.back(); } - const_reference back() const { return c.back(); } + reference front() { return Base::c.front(); } + const_reference front() const { return Base::c.front(); } + reference back() { return Base::c.back(); } + const_reference back() const { return Base::c.back(); } /* Insert and delete operations */ iterator insert(const_iterator position, Handle<T> h) { - value_type v = owner->acquire(h); + value_type v = Base::owner->acquire(h); addManaged(v); - return c.insert(position, owner->acquire(h)); + return Base::c.insert(position, v); } template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last) { - bool first = true; + bool atStart = true; const_iterator pos = position; for (InputIterator it = first; it != last; it++) { - if (first) { - first = false; + if (atStart) { + atStart = false; } else { pos++; } @@ -191,51 +202,51 @@ public: iterator find(const Handle<T> h) { - for (iterator it = begin(); it != end(); it++) { + for (iterator it = Base::begin(); it != Base::end(); it++) { if (*it == h) { return it; } } - return end(); + return Base::end(); } const_iterator find(const Handle<T> h) const { - for (const_iterator it = cbegin(); it != cend(); it++) { + for (const_iterator it = Base::cbegin(); it != Base::cend(); it++) { if (*it == h) { return it; } } - return cend(); + return Base::cend(); } void push_back(Handle<T> h) { - Rooted<T> rooted{h}; - addManaged(rooted); - c.push_back(owner->acquire(rooted)); + value_type v = Base::owner->acquire(h); + this->addManaged(v); + Base::c.push_back(v); } void pop_back() { - if (!empty()) { - deleteElement(c.back()); + if (!Base::empty()) { + this->deleteManaged(back()); } - c.pop_back(); + Base::c.pop_back(); } iterator erase(iterator position) { - deleteManaged(*position); - return c.erase(position); + this->deleteManaged(*position); + return Base::c.erase(position); } iterator erase(iterator first, iterator last) { for (const_iterator it = first; it != last; it++) { - deleteManaged(*it); + this->deleteManaged(*it); } - return c.erase(first, last); + return Base::c.erase(first, last); } }; @@ -243,15 +254,29 @@ public: * Special type of ManagedContainer based on an STL map. */ template <class K, class T, class Collection> -class ManagedGenericMap : public ManagedCollection<T, Collection> { +class ManagedGenericMap : public ManagedContainer<T, Collection> { +private: + using Base = ManagedContainer<T, Collection>; + +public: + using Base::ManagedContainer; + using collection_type = typename Base::collection_type; + using value_type = typename Base::value_type; + using key_type = typename Base::key_type; + using reference = typename Base::reference; + using const_reference = typename Base::const_reference; + using iterator = typename Base::iterator; + using const_iterator = typename Base::const_iterator; + using size_type = typename Base::size_type; + private: value_type acquirePair(std::pair<K, Handle<T>> val) { - return std::pair<const K, T>{val->first, owner->acquire(val->second)}; + return std::pair<const K, T>{val->first, + Base::owner->acquire(val->second)}; } public: - /** * Initialize with an iterator from another collection. * @@ -263,7 +288,8 @@ public: * from some other collection. */ template <class InputIterator> - ManagedGenericMap(Handle<Managed> owner, InputIterator first, InputIterator last) + ManagedGenericMap(Handle<Managed> owner, InputIterator first, + InputIterator last) : ManagedContainer<T, Collection>(owner) { insert(first, last); @@ -290,14 +316,14 @@ public: { value_type v = acquirePair(val); addManaged(v); - return c.insert(v); + return Base::c.insert(v); } iterator insert(const_iterator position, std::pair<K, Handle<T>> val) { value_type v = acquirePair(val); addManaged(v); - return c.insert(position, v); + return Base::c.insert(position, v); } template <class InputIterator> @@ -310,14 +336,14 @@ public: iterator erase(const_iterator position) { - deleteManaged(*position); - return c.erase(position); + Base::deleteManaged(*position); + return Base::c.erase(position); } size_t erase(const key_type &k) { iterator pos = find(k); - if (pos != end()) { + if (pos != Base::end()) { erase(pos); return 1; } @@ -327,13 +353,13 @@ public: iterator erase(const_iterator first, const_iterator last) { for (const_iterator it = first; it != last; it++) { - deleteManaged(*it); + Base::deleteManaged(*it); } - return c.erase(first, last); + return Base::c.erase(first, last); } - iterator find(const key_type &k) { return c.find(k); } - const_iterator find(const key_type &k) const { return c.find(k); } + iterator find(const key_type &k) { return Base::c.find(k); } + const_iterator find(const key_type &k) const { return Base::c.find(k); } }; /** @@ -342,7 +368,7 @@ public: template <class T> class ManagedVector : public ManagedGenericList<T, std::vector<Owned<T>>> { public: - using ManagedContainer<T, std::vector<Owned<T>>>::ManagedContainer; + using ManagedGenericList<T, std::vector<Owned<T>>>::ManagedGenericList; }; /** @@ -351,9 +377,8 @@ public: template <class K, class T> class ManagedMap : public ManagedGenericMap<K, T, std::map<K, Owned<T>>> { public: - using ManagedGenericMap<K, T, std::map<K, Owned<T>>>::ManagedMap; + using ManagedGenericMap<K, T, std::map<K, Owned<T>>>::ManagedGenericMap; }; - } #endif /* _OUSIA_MANAGED_CONTAINERS_H_ */ diff --git a/test/core/ManagedContainersTest.cpp b/test/core/ManagedContainersTest.cpp new file mode 100644 index 0000000..3abbd4d --- /dev/null +++ b/test/core/ManagedContainersTest.cpp @@ -0,0 +1,80 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <array> + +#include <gtest/gtest.h> + +#include <core/Managed.hpp> +#include <core/ManagedContainers.hpp> + +#include "TestManaged.hpp" + +namespace ousia { + +TEST(ManagedVector, managedVector) +{ + // TODO: This test is highly incomplete + + constexpr int nElem = 16; + std::array<bool, nElem> a; + + Manager mgr(1); + { + Rooted<Managed> root{new Managed{mgr}}; + + std::vector<TestManaged*> elems; + for (int i = 0; i < nElem; i++) { + elems.push_back(new TestManaged{mgr, a[i]}); + } + + for (bool v : a) { + ASSERT_TRUE(v); + } + + ManagedVector<TestManaged> v(root, elems); + + // Remove the last element from the list. It should be garbage collected. + v.pop_back(); + ASSERT_FALSE(a[nElem - 1]); + + // Insert a new element into the list. + v.push_back(new TestManaged{mgr, a[nElem - 1]}); + ASSERT_TRUE(a[nElem - 1]); + + // Erase element 10 + { + auto it = v.find(elems[10]); + ASSERT_TRUE(it != v.end()); + v.erase(it); + ASSERT_FALSE(a[10]); + } + + // Erase element 3 - 5 + v.erase(v.find(elems[3]), v.find(elems[5])); + ASSERT_FALSE(a[3] || a[4]); + ASSERT_TRUE(a[5]); + } + + for (bool v : a) { + ASSERT_FALSE(v); + } +} + +} + diff --git a/test/core/ManagedTest.cpp b/test/core/ManagedTest.cpp index 1aada5a..a52ba88 100644 --- a/test/core/ManagedTest.cpp +++ b/test/core/ManagedTest.cpp @@ -24,6 +24,8 @@ #include <core/Managed.hpp> +#include "TestManaged.hpp" + namespace ousia { /* Class ObjectDescriptor */ @@ -211,39 +213,6 @@ TEST(Owned, equalsAndAssign) /* Class Manager */ -class TestManaged : public Managed { -private: - bool &alive; - - std::vector<Owned<Managed>> refs; - -public: - TestManaged(Manager &mgr, bool &alive) : Managed(mgr), alive(alive) - { - //std::cout << "create TestManaged @" << this << std::endl; - alive = true; - } - - ~TestManaged() override - { - //std::cout << "delete TestManaged @" << this << std::endl; - alive = false; - } - - void addRef(Handle<Managed> h) { refs.push_back(acquire(h)); } - - void deleteRef(Handle<Managed> h) - { - for (auto it = refs.begin(); it != refs.end();) { - if (*it == h) { - it = refs.erase(it); - } else { - it++; - } - } - } -}; - TEST(Manager, linearDependencies) { std::array<bool, 4> a; @@ -542,54 +511,5 @@ TEST(Manager, hiddenRootedGraph) } } -TEST(ManagedVector, managedVector) -{ - // TODO: This test is highly incomplete - - constexpr int nElem = 16; - std::array<bool, nElem> a; - - Manager mgr(1); - { - Rooted<Managed> root{new Managed{mgr}}; - - std::vector<TestManaged*> elems; - for (int i = 0; i < nElem; i++) { - elems.push_back(new TestManaged{mgr, a[i]}); - } - - for (bool v : a) { - ASSERT_TRUE(v); - } - - ManagedVector<TestManaged> v(root, elems); - - // Remove the last element from the list. It should be garbage collected. - v.pop_back(); - ASSERT_FALSE(a[nElem - 1]); - - // Insert a new element into the list. - v.push_back(new TestManaged{mgr, a[nElem - 1]}); - ASSERT_TRUE(a[nElem - 1]); - - // Erase element 10 - { - auto it = v.find(elems[10]); - ASSERT_TRUE(it != v.end()); - v.erase(it); - ASSERT_FALSE(a[10]); - } - - // Erase element 3 - 5 - v.erase(v.find(elems[3]), v.find(elems[5])); - ASSERT_FALSE(a[3] || a[4]); - ASSERT_TRUE(a[5]); - } - - for (bool v : a) { - ASSERT_FALSE(v); - } -} - } diff --git a/test/core/TestManaged.hpp b/test/core/TestManaged.hpp new file mode 100644 index 0000000..3b93e51 --- /dev/null +++ b/test/core/TestManaged.hpp @@ -0,0 +1,62 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TEST_MANAGED_H_ +#define _TEST_MANAGED_H_ + +#include <core/Managed.hpp> + +namespace ousia { + +class TestManaged : public Managed { +private: + bool &alive; + + std::vector<Owned<Managed>> refs; + +public: + TestManaged(Manager &mgr, bool &alive) : Managed(mgr), alive(alive) + { + //std::cout << "create TestManaged @" << this << std::endl; + alive = true; + } + + ~TestManaged() override + { + //std::cout << "delete TestManaged @" << this << std::endl; + alive = false; + } + + void addRef(Handle<Managed> h) { refs.push_back(acquire(h)); } + + void deleteRef(Handle<Managed> h) + { + for (auto it = refs.begin(); it != refs.end();) { + if (*it == h) { + it = refs.erase(it); + } else { + it++; + } + } + } +}; + +} + +#endif /* _TEST_MANAGED_H_ */ + |