summaryrefslogtreecommitdiff
path: root/src/core/managed/ManagedContainer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/managed/ManagedContainer.hpp')
-rw-r--r--src/core/managed/ManagedContainer.hpp520
1 files changed, 352 insertions, 168 deletions
diff --git a/src/core/managed/ManagedContainer.hpp b/src/core/managed/ManagedContainer.hpp
index 7b18bcd..1454608 100644
--- a/src/core/managed/ManagedContainer.hpp
+++ b/src/core/managed/ManagedContainer.hpp
@@ -16,6 +16,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * @file ManagedContainer.hpp
+ *
+ * Container classes for conviniently storing managed instances.
+ *
+ * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
+ */
+
#ifndef _OUSIA_MANAGED_CONTAINER_H_
#define _OUSIA_MANAGED_CONTAINER_H_
@@ -31,48 +39,140 @@
namespace ousia {
/**
+ * Default accessor class for accessing the managed element within a list value
+ * type.
+ *
+ * @tparam ValueType is the list value type that should be accessed.
+ */
+template <class ValueType>
+struct ListAccessor {
+ Managed *getManaged(const ValueType &val) const { return val.get(); }
+};
+
+/**
+ * Default accessor class for accessing the managed element within a map value
+ * type.
+ *
+ * @tparam ValueType is the map value type that should be accessed.
+ */
+template <class ValueType>
+struct MapAccessor {
+ Managed *getManaged(const ValueType &val) const { return val.second.get(); }
+};
+
+/**
+ * Default implementation of a Listener class. With empty functions.
+ */
+template <class ValueType>
+struct DefaultListener {
+ void addElement(const ValueType &val, Managed *owner) {}
+ void deleteElement(const ValueType &val, Managed *owner) {}
+};
+
+/**
* Template class which can be used to collect refrences to a certain type of
* managed objects. Do not use this class directly, use ManagedMap or
* ManagedVector instead. This class only provides functionality which is common
* to list and map containers (iterators and state).
*
- * @param T is the type of the Managed object that should be managed.
- * @param Collection should be a STL container of Owned<T>
+ * @tparam T is the type of the Managed object that should be managed.
+ * @tparam Collection is the underlying STL collection and should contain
+ * pointers of type T as value.
+ * @tparam Accessor is a type that allows to resolve the STL value type to the
+ * actual, underlying pointer to T -- this is important to generically support
+ * maps, where the value type is a pair of key type and the actual value.
+ * @tparam Listener is an optional type that allows to execute arbitrary code
+ * whenever data is read or written to the collection.
*/
-template <class T, class Collection>
-class ManagedContainer : Managed {
+template <class T, class Collection, class Accessor, class Listener>
+class ManagedContainer {
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;
+ using own_type = ManagedContainer<T, Collection, Accessor, Listener>;
+ using value_type = typename Collection::value_type;
+ using reference = typename Collection::reference;
+ using const_reference = typename Collection::const_reference;
+ using iterator = typename Collection::iterator;
+ using const_iterator = typename Collection::const_iterator;
+ using size_type = typename Collection::size_type;
-protected:
+private:
/**
* Handle containing a reference to the owner of the collection.
*/
- Handle<Managed> owner;
+ Managed *owner;
/**
- * Underlying STL collection.
+ * Accessor used to access the managed instance inside a "reference type".
+ */
+ Accessor accessor;
+
+ /**
+ * Listener which is notified whenever an element is added to or removed
+ * from the list.
+ */
+ Listener listener;
+
+ /**
+ * Calls the "addElement" function of each element and thus initializes
+ * the references from the owner to the elements.
+ */
+ void initialize()
+ {
+ for (const auto &elem : *this) {
+ addElement(elem);
+ }
+ }
+
+ /**
+ * Calls the "deleteElement" function of each element and thus finalizes
+ * the references from the owner to the elements.
*/
- collection_type c;
+ void finalize()
+ {
+ if (owner) {
+ for (const auto &elem : *this) {
+ deleteElement(elem);
+ }
+ }
+ }
protected:
/**
- * Function which can be overridden by child classes to execute special code
- * whenever a new element is added to the collection.
+ * Underlying STL collection.
+ */
+ Collection c;
+
+ /**
+ * Function to be called whenever an element is added to the collection.
+ * This function makes sure that the association from the owner to the added
+ * element is established.
+ *
+ * @param managed is the managed instance that is being added to the
+ * container.
+ * @param elem is a reference to the actual element that is being added to
+ * the underlying container.
*/
- virtual void addElement(value_type h) {}
+ void addElement(const value_type &elem)
+ {
+ getManager().addRef(accessor.getManaged(elem), owner);
+ listener.addElement(elem, owner);
+ }
/**
- * Function which can be overriden by child classes to execute special code
- * whenever an element is removed from the collection.
+ * Function to be called whenever an element is removed from the collection.
+ * This function makes sure that the association from the owner to the added
+ * element is removed.
+ *
+ * @param managed is the managed instance that is being deleted from the
+ * container.
+ * @param elem is a reference to the actual element that is being removed
+ * from the underlying container.
*/
- virtual void deleteElement(value_type h) {}
+ void deleteElement(const value_type &elem)
+ {
+ getManager().deleteRef(accessor.getManaged(elem), owner);
+ listener.deleteElement(elem, owner);
+ }
public:
/**
@@ -81,15 +181,162 @@ public:
* @param owner is the managed object which owns the collection and all
* handles to other managed objects stored within.
*/
- ManagedContainer(Handle<Managed> owner) : Managed(owner->getManager), owner(owner){};
+ ManagedContainer(Handle<Managed> owner) : owner(owner.get()){};
+
+ /**
+ * Copy constructor. Creates a copy of the given container with the same
+ * owner as the given container.
+ *
+ * @param other is the other coontainer that should be copied.
+ */
+ ManagedContainer(const own_type &other) : owner(other.owner), c(other.c)
+ {
+ initialize();
+ }
+
+ /**
+ * Copy constructor. Creates a copy of the given container with another
+ * owner.
+ *
+ * @param other is the other container that should be copied.
+ */
+ ManagedContainer(Handle<Managed> owner, const own_type &other)
+ : owner(owner.get()), c(other.c)
+ {
+ initialize();
+ }
+
+ /**
+ * Copy constructor. Creates a copy of the given container and takes over
+ * ownership.
+ */
+ ManagedContainer(Handle<Managed> owner, const Collection &collection)
+ : owner(owner), c(collection)
+ {
+ initialize();
+ }
+
+ /**
+ * Move constructor. Moves the other instance to this instance.
+ *
+ * @param other is the other container that should be moved.
+ */
+ ManagedContainer(own_type &&other)
+ : owner(other.owner), c(std::move(other.c))
+ {
+ other.owner = nullptr;
+ }
+
+ /**
+ * Copy constructor. Creates a copy of the given container with another
+ * owner.
+ *
+ * @param other is the other container that should be moved.
+ */
+ ManagedContainer(Handle<Managed> owner, own_type &&other)
+ : owner(owner.get()), c(std::move(other.c))
+ {
+ other.finalize();
+ other.owner = nullptr;
+ initialize();
+ }
+
+ /**
+ * Copy constructor. 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>
+ ManagedContainer(Handle<Managed> owner, InputIterator first,
+ InputIterator last)
+ : owner(owner.get())
+ {
+ auto it = end();
+ for (auto it2 = first; it2 != last; it2++) {
+ it = insert(it, *it2);
+ it++;
+ }
+ }
+
+ /**
+ * Destructor of the ManagedContainer class. Calls the "deleteElement"
+ * function for each element in the container.
+ */
+ ~ManagedContainer() { finalize(); };
+
+ /**
+ * Copy assignment operator.
+ *
+ * @param other is the collection instance that should be copied.
+ * @return this instance.
+ */
+ own_type &operator=(const own_type &other)
+ {
+ finalize();
+ owner = other.owner;
+ c = other.c;
+ initialize();
+ return *this;
+ }
+
+ /**
+ * Move assignment operator.
+ *
+ * @param other is the collection instance that should be moved;
+ * @return this instance.
+ */
+ own_type &operator=(own_type &&other)
+ {
+ finalize();
+ owner = other.owner;
+ c = std::move(other.c);
+ other.owner = nullptr;
+ return *this;
+ }
+
+ /**
+ * Equality operator.
+ */
+ bool operator==(const own_type &other) {
+ return (owner == other.owner) && (c == other.c);
+ }
+
+ /**
+ * Inequality operator.
+ */
+ bool operator!=(const own_type &other) {
+ return (owner != other.owner) || (c != other.c);
+ }
/**
- * Destructor of the ManagedContainer class.
+ * Returns the owner of the ManagedContainer instance.
*/
- virtual ~ManagedContainer() {};
+ Managed *getOwner() { return owner; }
+
+ /**
+ * Returns the manager instance associated with the owner.
+ */
+ Manager &getManager() { return owner->getManager(); }
/* State functions */
+
+ /**
+ * Returns the size of the container.
+ *
+ * @return the number of elements in the container.
+ */
size_type size() const noexcept { return c.size(); }
+
+ /**
+ * Returns whether the container is empty.
+ *
+ * @return true if the container is empty, false otherwise.
+ */
bool empty() const noexcept { return c.empty(); }
/* Iterators */
@@ -111,7 +358,9 @@ public:
const_iterator crbegin() const { return c.crbegin(); }
const_iterator crend() const { return c.crend(); }
- /* Clear function */
+ /**
+ * Removes all elements from the container.
+ */
void clear() noexcept
{
for (const_iterator it = cbegin(); it != cend(); it++) {
@@ -119,6 +368,41 @@ public:
}
c.clear();
}
+
+ /**
+ * Generic insert operation.
+ */
+ iterator insert(const_iterator position, value_type val)
+ {
+ addElement(val);
+ return c.insert(position, val);
+ }
+
+ /**
+ * Erases the element at the given position.
+ *
+ * @param position is the position at which the element should be removed.
+ * @return an iterator to the element after the deleted element.
+ */
+ iterator erase(iterator position)
+ {
+ deleteElement(*position);
+ return c.erase(position);
+ }
+
+ /**
+ * Erases a range of elements from the collection.
+ *
+ * @param position is the position at which the element should be removed.
+ * @return an iterator to the element after the deleted element.
+ */
+ iterator erase(iterator first, iterator last)
+ {
+ for (const_iterator it = first; it != last; it++) {
+ this->deleteElement(*it);
+ }
+ return c.erase(first, last);
+ }
};
/**
@@ -128,16 +412,15 @@ public:
* 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 list container of Owned<T>
+ * @param Collection should be a STL list container of T*
*/
-template <class T, class Collection>
-class ManagedGenericList : public ManagedContainer<T, Collection> {
+template <class T, class Collection, class Accessor, class Listener>
+class ManagedGenericList
+ : public ManagedContainer<T, Collection, Accessor, Listener> {
private:
- using Base = ManagedContainer<T, Collection>;
+ using Base = ManagedContainer<T, Collection, Accessor, Listener>;
public:
- 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;
@@ -145,40 +428,8 @@ public:
using const_iterator = typename Base::const_iterator;
using size_type = typename Base::size_type;
- /**
- * 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>
- ManagedGenericList(Handle<Managed> owner, InputIterator first,
- InputIterator last)
- : ManagedContainer<T, Collection>(owner)
- {
- insert(Base::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>
- ManagedGenericList(Handle<Managed> owner, const InputCollection &in)
- : ManagedContainer<T, Collection>(owner)
- {
- for (const auto &e : in) {
- push_back(e);
- }
- }
+ using Base::ManagedContainer;
+ using Base::insert;
/* Front and back */
reference front() { return Base::c.front(); }
@@ -188,13 +439,6 @@ public:
/* Insert and delete operations */
- iterator insert(const_iterator position, Handle<T> h)
- {
- value_type v = Base::owner->acquire(h);
- addElement(v);
- return Base::c.insert(position, v);
- }
-
template <class InputIterator>
iterator insert(const_iterator position, InputIterator first,
InputIterator last)
@@ -212,20 +456,20 @@ public:
return pos;
}
- iterator find(const Handle<T> h)
+ iterator find(const value_type &val)
{
for (iterator it = Base::begin(); it != Base::end(); it++) {
- if (*it == h) {
+ if (*it == val) {
return it;
}
}
return Base::end();
}
- const_iterator find(const Handle<T> h) const
+ const_iterator find(const value_type &val) const
{
for (const_iterator it = Base::cbegin(); it != Base::cend(); it++) {
- if (*it == h) {
+ if (*it == val) {
return it;
}
}
@@ -234,9 +478,8 @@ public:
void push_back(Handle<T> h)
{
- value_type v = Base::owner->acquire(h);
- this->addElement(v);
- Base::c.push_back(v);
+ this->addElement(h.get());
+ Base::c.push_back(h.get());
}
void pop_back()
@@ -246,33 +489,18 @@ public:
}
Base::c.pop_back();
}
-
- iterator erase(iterator position)
- {
- this->deleteElement(*position);
- return Base::c.erase(position);
- }
-
- iterator erase(iterator first, iterator last)
- {
- for (const_iterator it = first; it != last; it++) {
- this->deleteElement(*it);
- }
- return Base::c.erase(first, last);
- }
};
/**
* Special type of ManagedContainer based on an STL map.
*/
-template <class K, class T, class Collection>
-class ManagedGenericMap : public ManagedContainer<T, Collection> {
+template <class K, class T, class Collection, class Accessor, class Listener>
+class ManagedGenericMap
+ : public ManagedContainer<T, Collection, Accessor, Listener> {
private:
- using Base = ManagedContainer<T, Collection>;
+ using Base = ManagedContainer<T, Collection, Accessor, Listener>;
public:
- using Base::ManagedContainer;
- using collection_type = typename Base::collection_type;
using value_type = typename Base::value_type;
using key_type = typename Collection::key_type;
using reference = typename Base::reference;
@@ -281,76 +509,30 @@ public:
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 value_type{val.first, Base::owner->acquire(val.second)};
- }
-
-public:
- /**
- * 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>
- ManagedGenericMap(Handle<Managed> owner, InputIterator first,
- InputIterator last)
- : ManagedContainer<T, Collection>(owner)
- {
- insert(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>
- ManagedGenericMap(Handle<Managed> owner, const InputCollection &in)
- : ManagedContainer<T, Collection>(owner)
- {
- for (const auto &e : in) {
- insert(*in);
- }
- }
+ using Base::ManagedContainer;
+ using Base::erase;
+ using Base::insert;
- std::pair<iterator, bool> insert(std::pair<K, Handle<T>> val)
+ std::pair<iterator, bool> insert(value_type val)
{
- value_type v = acquirePair(val);
- this->addElement(v);
- return Base::c.insert(v);
+ this->addElement(val);
+ return Base::c.insert(val);
}
- iterator insert(const_iterator position, std::pair<K, Handle<T>> val)
+ iterator insert(const_iterator position, value_type val)
{
- value_type v = acquirePair(val);
- this->addElement(v);
- return Base::c.insert(position, v);
+ this->addElement(val);
+ return Base::c.insert(position, val);
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
for (auto it = first; it != last; it++) {
- insert(acquirePair);
+ insert(*it);
}
}
- iterator erase(const_iterator position)
- {
- this->deleteElement(*position);
- return Base::c.erase(position);
- }
-
size_t erase(const key_type &k)
{
iterator pos = find(k);
@@ -361,14 +543,6 @@ public:
return 0;
}
- iterator erase(const_iterator first, const_iterator last)
- {
- for (const_iterator it = first; it != last; it++) {
- this->deleteElement(*it);
- }
- return Base::c.erase(first, last);
- }
-
iterator find(const key_type &k) { return Base::c.find(k); }
const_iterator find(const key_type &k) const { return Base::c.find(k); }
};
@@ -376,19 +550,29 @@ public:
/**
* Special type of ManagedGenericList based on an STL vector.
*/
-template <class T>
-class ManagedVector : public ManagedGenericList<T, std::vector<Owned<T>>> {
+template <class T, class Listener = DefaultListener<Handle<T>>>
+class ManagedVector
+ : public ManagedGenericList<T, std::vector<Handle<T>>,
+ ListAccessor<Handle<T>>, Listener> {
public:
- using ManagedGenericList<T, std::vector<Owned<T>>>::ManagedGenericList;
+ using Base = ManagedGenericList<T, std::vector<Handle<T>>,
+ ListAccessor<Handle<T>>, Listener>;
+ using Base::ManagedGenericList;
};
/**
* Special type of ManagedGenericMap based on an STL map.
*/
-template <class K, class T>
-class ManagedMap : public ManagedGenericMap<K, T, std::map<K, Owned<T>>> {
+template <class K, class T,
+ class Listener = DefaultListener<std::pair<K, Handle<T>>>>
+class ManagedMap
+ : public ManagedGenericMap<K, T, std::map<K, Handle<T>>,
+ MapAccessor<std::pair<K, Handle<T>>>, Listener> {
public:
- using ManagedGenericMap<K, T, std::map<K, Owned<T>>>::ManagedGenericMap;
+ using Base =
+ ManagedGenericMap<K, T, std::map<K, Handle<T>>,
+ MapAccessor<std::pair<K, Handle<T>>>, Listener>;
+ using Base::ManagedGenericMap;
};
}