From 467d8d52ffda8b5d520ee0eb1e42125bdb533ff4 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sat, 13 Dec 2014 12:33:07 +0100 Subject: started to refactor Managed package --- src/core/managed/Managed.hpp | 504 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 504 insertions(+) create mode 100644 src/core/managed/Managed.hpp (limited to 'src/core/managed/Managed.hpp') diff --git a/src/core/managed/Managed.hpp b/src/core/managed/Managed.hpp new file mode 100644 index 0000000..04c2f84 --- /dev/null +++ b/src/core/managed/Managed.hpp @@ -0,0 +1,504 @@ +/* + 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 . +*/ + +#ifndef _OUSIA_MANAGED_HPP_ +#define _OUSIA_MANAGED_HPP_ + +#include "Manager.hpp" + +namespace ousia { + +template +class Handle; + +template +class Rooted; + +template +class Owned; + +// TODO: Implement clone, getReferenced and getReferencing + +/** + * The Managed class represents a garbage collected object. Instances of the + * Managed class are managed (e.g. freed) by an instance of the Manager class. + * Never free instances of this class yourself (even by playing an instance of + * this class on the steck). Create any new instance of any managed object with + * the makeRooted and makeOwned functions. + */ +class Managed { +protected: + /** + * mgr is the reference to the managed object manager which owns this + * managed object. + */ + Manager &mgr; + +public: + /** + * Constructor of the Managed class. Associates the new instance with the + * given Manager, which is now in charge for managing this instance. Never + * manually free instances of this class (even by using stack instances). + * Always use the Rooted and Owned smart pointer classes when refering to + * types derived from Managed. + * + * @param mgr is the Manager which should take ownership of this instance. + */ + Managed(Manager &mgr) : mgr(mgr) { mgr.manage(this); }; + + /** + * Virtual destuctor which may be overwritten by child classes. + */ + virtual ~Managed(){}; + + /** + * Returns a reference ot the manager instance which owns this managed + * object. + */ + Manager &getManager() { return mgr; } + + /** + * Acquires a reference to the object wraped in the given handle. + */ + template + Owned acquire(const Handle &h) + { + return Owned{h, this}; + } + + template + Owned acquire(Handle &&h) + { + return Owned{h, this}; + } + + template + Owned acquire(T *t) + { + return Owned{t, this}; + } + + template + std::vector> acquire(const std::vector> &vec) + { + std::vector> res; + for (auto &e : vec) { + res.push_back(acquire(e)); + } + return res; + } + + template + std::vector> acquire(const std::vector &vec) + { + std::vector> res; + for (auto &e : vec) { + res.push_back(acquire(e)); + } + return res; + } +}; + +/** + * The Handle class is the base class for handles pointing at managed objects. + * It implements methods for comparing handles to each other and to pointers + * of the represented managed object type. Furthermore all other handle types + * and pointers can be conveniently converted to a Handle instance. However, + * the Handle class does not qualify the represented pointer for garbage + * collection. Thus the Handle class should only be used as type for input + * parameters in methods/functions and at no other ocasion. Use the Rooted or + * the Owned class if the represented object should actually be garbage + * collected. + */ +template +class Handle { +protected: + friend class Rooted; + friend class Owned; + + /** + * Reference to the represented managed object. + */ + T *ptr; + +public: + /** + * Constructor of the base Handle class. + * + * @param ptr is the pointer to the managed object the Handle should + * represent. + */ + Handle(T *ptr) : ptr(ptr) {} + + /** + * Copies the given Handle to this Handle instance. + * + * @param h is the Handle that should be asigned to this instance. + */ + Handle(const Handle &h) : ptr(h.get()) {} + + /** + * Copies the given Handle for a managed object of a derived class to this + * Handle instance. + * + * @param h is the Handle that should be asigned to this instance. + */ + template + Handle(const Handle &h) + : ptr(h.get()) + { + } + + /** + * Returns the underlying pointer. + */ + T *get() const { return ptr; } + + /** + * Provides access to the underlying managed object. + */ + T *operator->() { return ptr; } + + /** + * Provides access to the underlying managed object for immutable handles. + */ + const T *operator->() const { return ptr; } + + /** + * Provides access to the underlying managed object. + */ + T &operator*() { return *ptr; } + + /** + * Provides access to the underlying managed object for immutable handles. + */ + const T &operator*() const { return *ptr; } + + /** + * Comparison operator between base Owned and base Owned. + */ + template + bool operator==(const Handle &h) const + { + return ptr == h.get(); + } + + /** + * Comparison operator between base Owned and pointer. + */ + friend bool operator==(const Handle &h, const Managed *o) + { + return h.get() == o; + } + + /** + * Comparison operator between base Owned and pointer. + */ + friend bool operator==(const Managed *o, const Handle &h) + { + return o == h.get(); + } + + /** + * Returns true if the handle is the null pointer. + */ + bool isNull() const { return ptr == nullptr; } + + /** + * Returns true if the handle is the null pointer. + */ + bool operator!() const { return isNull(); } + + /** + * Statically casts the handle to a handle of the given type. + */ + template + Handle cast() + { + return Handle{static_cast(ptr)}; + } +}; + +/** + * A Rooted represents a directed, garbage collected pointer at a managed + * object. The lifetime of the represented managed object is guaranteed to be at + * least as long as the lifetime of the Rooted handle instance. + */ +template +class Rooted : public Handle { +private: + void addRef() + { + if (Handle::ptr) { + Handle::ptr->getManager().addRef(Handle::ptr, nullptr); + } + } + + void deleteRef() + { + if (Handle::ptr) { + Handle::ptr->getManager().deleteRef(Handle::ptr, nullptr); + } + } + +public: + /** + * Creates an empty Owned. + */ + Rooted() : Handle(nullptr){}; + + /** + * Copies the given Rooted to this Rooted instance. Both handles + * are indistinguishable after the operation. + * + * @param h is the Owned that should be asigned to this instance. + */ + Rooted(const Rooted &h) : Handle(h.ptr) { addRef(); } + + /** + * Move constructor. Moves the given rvalue Rooted to this instance. + * + * @param h is the Rooted to be moved to this instance. + */ + Rooted(Rooted &&h) : Handle(h.ptr) { h.ptr = nullptr; } + + /** + * Constructor of the Rooted class. + * + * @param ptr is the managed object the Rooted handle should represent. + */ + Rooted(T *ptr) : Handle(ptr) { addRef(); } + + /** + * Constructor of the Rooted class. + * + * @param h is another Rooted whose managed object should be used. + */ + template + Rooted(const Handle &h) + : Handle(h.get()) + { + addRef(); + } + + /** + * Assignment operator. Assigns the given Owned to this Owned instance. + * Both handles are indistinguishable after the operation. + * + * @param h is the Owned that should be asigned to this instance. + */ + Rooted &operator=(const Rooted &h) + { + deleteRef(); + this->ptr = h.ptr; + addRef(); + return *this; + } + + /** + * Move assignment operator. Moves the given rvalue Owned into this + * instance. + * + * @param h is the Owned to be moved to this instance. + */ + Rooted &operator=(Rooted &&h) + { + deleteRef(); + this->ptr = h.ptr; + h.ptr = nullptr; + return *this; + } + + /** + * Assignment operator. Assigns the given Owned to this Owned instance. + * Both handles are indistinguishable after the operation. + * + * @param h is the Owned that should be asigned to this instance. + */ + template + Rooted &operator=(const Handle &h) + { + deleteRef(); + this->ptr = h.get(); + addRef(); + return *this; + } + + /** + * Move assignment operator. Moves the given rvalue Owned into this + * instance. + * + * @param h is the Owned to be moved to this instance. + */ + Rooted &operator=(Handle &&h) + { + deleteRef(); + this->ptr = h.ptr; + h.ptr = nullptr; + return *this; + } + + /** + * Destructor of the Rooted class, deletes all refrences the class is + * still holding. + */ + ~Rooted() { deleteRef(); } +}; + +/** + * The Owned class represents a directed, garbage collected pointer at a managed + * instance. The lifetime of the represented managed object is guaranteed to be + * at last as long as the lifetime of the Managed instance which owns this + * reference. + */ +template +class Owned : public Handle { +private: + Managed *owner; + + void addRef() + { + if (Handle::ptr && owner) { + owner->getManager().addRef(Handle::ptr, owner); + } + } + + void deleteRef() + { + if (Handle::ptr && owner) { + owner->getManager().deleteRef(Handle::ptr, owner); + } + } + +public: + /** + * Creates an empty Owned. + */ + Owned() : Handle(nullptr), owner(nullptr){}; + + /** + * Copies the given Owned to this Owned instance. Both handles are + * indistinguishable after the operation. Note that especially the Owned + * owner is copied. + * + * @param h is the Owned that should be asigned to this instance. + */ + Owned(const Owned &h) : Handle(h.get()), owner(h.getOwner()) + { + addRef(); + } + + /** + * Copies the given Owned of another derived type to this Owned instance. + * Both handles are indistinguishable after the operation (except for the + * type). Note that especially the Owned owner is copied. + * + * @param h is the Owned that should be asigned to this instance. + */ + template + Owned(const Owned &h) + : Handle(h.get()), owner(h.getOwner()) + { + addRef(); + } + + /** + * Move constructor. Moves the given rvalue Owned to this instance. + * + * @param h is the Owned to be moved to this instance. + */ + Owned(Owned &&h) : Handle(h.get()), owner(h.getOwner()) + { + h.ptr = nullptr; + } + + /** + * Assignment operator. Assigns the given Owned to this Owned instance. + * Both handles are indistinguishable after the operation. Note that + * especially the Owned owner is copied. + * + * @param h is the Owned that should be asigned to this instance. + */ + Owned &operator=(const Owned &h) + { + deleteRef(); + this->ptr = h.ptr; + this->owner = h.getOwner(); + addRef(); + return *this; + } + + /** + * Move assignment operator. Moves the given rvalue Owned into this + * instance. + * + * @param h is the Owned to be moved to this instance. + */ + Owned &operator=(Owned &&h) + { + deleteRef(); + this->ptr = h.ptr; + this->owner = h.getOwner(); + h.ptr = nullptr; + return *this; + } + + /** + * Constructor of the Owned class. + * + * @param ptr is a pointer at the managed object the Owned handle should + * represent. + * @param owner is the managed object which owns this Owned handle instance. + * The managed object pointed to in the handle is guaranteed to live at + * least as long as the owner. + */ + Owned(T *ptr, Managed *owner) : Handle(ptr), owner(owner) { addRef(); } + + /** + * Constructor of the Owned class. + * + * @param h is another Owned whose managed object should be used. + * @param owner is the managed object which owns this Owned handle instance. + * The managed object pointed to in the handle is guaranteed to live at + * least as long as the owner. + */ + template + Owned(const Handle &h, Managed *owner) + : Handle(h.get()), owner(owner) + { + addRef(); + } + + /** + * Destructor of the Owned class, deletes all refrences the class is still + * holding. + */ + ~Owned() { deleteRef(); } + + /** + * Returns the reference to the owner of the Owned. + * + * @return the Owned owner. + */ + Managed *getOwner() const { return owner; } +}; + +} + +#endif /* _OUSIA_MANAGED_HPP_ */ + -- cgit v1.2.3