/* Icinga 2 | (c) 2019 Icinga GmbH | GPLv2+ */ #ifndef SHARED_H #define SHARED_H #include "base/atomic.hpp" #include #include #include namespace icinga { template class Shared; template inline void intrusive_ptr_add_ref(Shared *object) { object->m_References.fetch_add(1); } template inline void intrusive_ptr_release(Shared *object) { if (object->m_References.fetch_sub(1) == 1u) { delete object; } } /** * Seemless wrapper for any class to create shared pointers of. * Saves a memory allocation compared to std::shared_ptr. * * @ingroup base */ template class Shared : public T { friend void intrusive_ptr_add_ref<>(Shared *object); friend void intrusive_ptr_release<>(Shared *object); public: typedef boost::intrusive_ptr Ptr; /** * Like std::make_shared, but for this class. * * @param args Constructor arguments * * @return Ptr */ template static inline Ptr Make(Args&&... args) { return new Shared(std::forward(args)...); } inline Shared(const Shared& origin) : Shared((const T&)origin) { } inline Shared(Shared&& origin) : Shared((T&&)origin) { } template inline Shared(Args&&... args) : T(std::forward(args)...), m_References(0) { } inline Shared& operator=(const Shared& rhs) { return operator=((const T&)rhs); } inline Shared& operator=(Shared&& rhs) { return operator=((T&&)rhs); } inline Shared& operator=(const T& rhs) { T::operator=(rhs); return *this; } inline Shared& operator=(T&& rhs) { T::operator=(std::move(rhs)); return *this; } private: Atomic m_References; }; } #endif /* SHARED_H */