17 struct SharedObj_tag {};
23 SharedControl() : _count(0), _weakCount(1) {}
26 void ref() { ++_count; }
28 bool refLock() {
int old;
do { old = _count;
if (old <= 0)
return false; }
while (!_count.cas(old+1,old));
return true; }
30 void unref() {
if (--_count > 0)
return; finalize(); }
32 int count()
const {
return _count; }
35 void refWeak() { ++_weakCount; }
37 void unrefWeak() {
if (--_weakCount > 0)
return; destroy(); }
39 int weakCount()
const {
return _weakCount; }
41 virtual void finalize() = 0;
42 virtual void destroy() = 0;
45 Atomic<int> _weakCount;
49 template<
class T,
class Fin,
class Alloc_>
50 struct SharedControl_ : SharedControl
52 typedef typename Alloc_::template rebind<SharedControl_>::other Alloc;
53 SharedControl_(T* ptr, Fin&& f, Alloc a) : _ptr(ptr), _fin(forward<Fin>(f)), _alloc(move(a)) {}
54 virtual void finalize() { _fin(_ptr); unrefWeak(); }
55 virtual void destroy() {
auto a = move(_alloc);
delete_(
this, a); }
63 template<class Subclass, class T, bool isIntrusive = mt::is_base_of<SharedObj_tag, T>::value>
64 struct SharedControlPtr
66 SharedControlPtr() : __control(nullptr) {}
67 SharedControl* _control()
const {
return __control; }
68 void _control(SharedControl* ptr) { __control = ptr; }
70 SharedControl* __control;
73 template<
class T,
class Alloc_>
struct SharedControl_obj;
92 template<
class Sub
class>
95 template<
class,
class,
bool>
friend struct priv::SharedControlPtr;
100 template<
class Alloc = std::allocator<Sub
class>>
105 new (&_controlStorage) Control(subc(), Alloc_(forward<Alloc>(a)));
110 void finalize() { Control& control = _control(); subc().~Subclass(); control.unrefWeak(); }
117 struct Control : priv::SharedControl
119 template<
class Alloc>
120 Control(Subclass& obj, Alloc&& a) : _obj(&obj), _dealloc([=](Subclass* p) mutable { a.deallocate(p,1); }) {}
122 virtual void finalize() { _obj->finalize(); }
124 virtual void destroy()
127 auto dealloc = move(_dealloc);
133 function<void (Subclass*)> _dealloc;
135 typedef typename std::aligned_storage<sizeof(Control), alignof(Control)>::type ControlStorage;
137 Subclass& subc() {
return static_cast<Subclass&
>(*this); }
139 Control& _control()
const {
return reinterpret_cast<Control&
>(_controlStorage); }
141 mutable ControlStorage _controlStorage;
149 template<
class Sub
class,
class T>
150 struct SharedControlPtr<Subclass, T, true>
152 SharedControl* _control()
const {
return subc()._ptr ? &subc()._ptr->SharedObj::_control() :
nullptr; }
153 void _control(SharedControl*) {}
155 const Subclass& subc()
const {
return static_cast<const Subclass&
>(*this); }
175 class SharedPtr : priv::SharedControlPtr<SharedPtr<T>, T>
177 typedef priv::SharedControlPtr<SharedPtr<T>, T> ControlPtr;
181 template<
class,
class>
friend struct priv::SharedControl_obj;
188 template<class T_, bool = std::is_void<T_>::value>
struct Ref_ {
typedef T_& type;
static type deref(T_* p) {
return *p; } };
189 template<
class T_>
struct Ref_<T_, true> {
typedef T_ type;
static type deref(T_* p) {} };
193 typedef typename Ref_<Elem>::type
Ref;
199 template<class U, typename std::enable_if<mt::True<U>::value && isIntrusive,
int>::type=0>
205 template<
class U,
class Fin = finalize<U>,
class Alloc =
typename DefaultAllocator<U>::type,
typename mt::disable_if<mt::True<U>::value && isIntrusive,
int>::type=0>
206 explicit SharedPtr(U* ptr, Fin&& f = Fin(), Alloc&& a = Alloc()) : _ptr(nullptr) { set(ptr, forward<Fin>(f), forward<Alloc>(a)); }
219 explicit SharedPtr(
const WeakPtr<U>& ptr) : _ptr(ptr._ptr) { this->_control(ptr._control());
if (_ptr && !getControl().refLock()) _ptr =
nullptr; }
222 template<
class U,
class Fin>
234 template<class U, class Fin, typename std::enable_if<mt::True<U>::value && isIntrusive,
int>::type=0>
236 template<class U, class Fin, typename mt::disable_if<mt::True<U>::value && isIntrusive,
int>::type=0>
244 bool operator< (const SharedPtr<U>& rhs)
const {
return std::less<typename std::common_type<T*,U*>::type>()(
get(), rhs.get()); }
248 bool operator<=(const SharedPtr<U>& rhs)
const {
return !
operator>(rhs); }
259 operator T*()
const {
return _ptr; }
262 T*
get()
const {
return _ptr; }
265 template<class U, typename std::enable_if<mt::True<U>::value && isIntrusive,
int>::type=0>
266 void set(U* ptr) { setControl(ptr, ptr ? &ptr->SharedObj::_control() :
nullptr); }
268 template<
class U,
class Fin = finalize<U>,
class Alloc =
typename DefaultAllocator<U>::type,
typename mt::disable_if<mt::True<U>::value && isIntrusive,
int>::type=0>
269 void set(U* ptr, Fin&& f = Fin(), Alloc&& a = Alloc())
271 typedef priv::SharedControl_<U,Fin,Alloc> Control;
272 typedef typename Alloc::template rebind<Control>::other Alloc_;
273 Alloc_ a_ = forward<Alloc>(a);
274 setControl(ptr, ptr ?
new (a_.allocate(1)) Control(ptr, forward<Fin>(f), move(a_)) :
nullptr);
276 void set(nullptr_t) {
set((T*)
nullptr); }
279 int refCount()
const {
if (_ptr)
return getControl().count();
return 0; }
281 bool unique()
const {
return refCount() == 1; }
284 template<
class U>
void set(
const SharedPtr<U>& rhs) { setControl(rhs._ptr, rhs._control()); }
285 template<
class U>
void set(SharedPtr<U>&& rhs) { moveControl(rhs._ptr, rhs._control()); rhs._ptr =
nullptr; rhs._control(
nullptr); }
288 void setControl(U* ptr, priv::SharedControl* control)
290 if (ptr) control->ref();
291 T* oldPtr = _ptr; priv::SharedControl* oldControl = this->_control();
292 _ptr = ptr; this->_control(control);
293 if (oldPtr) oldControl->unref();
297 void moveControl(U* ptr, priv::SharedControl* control)
299 if (_ptr && this->_control() != control)
300 this->_control()->unref();
301 _ptr = ptr; this->_control(control);
304 priv::SharedControl& getControl()
const {
assert(this->_control());
return *this->_control(); }
313 template<
class T,
class Alloc_>
314 struct SharedControl_obj : SharedControl
316 typedef typename mt::removeRef<Alloc_>::type::template rebind<SharedControl_obj>::other Alloc;
317 typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type Storage;
319 template<
class... Args>
320 static SharedPtr<T>
create(Alloc a, Args&&... args)
322 auto* control =
new (a.allocate(1)) SharedControl_obj(move(a), forward<Args>(args)...);
324 ptr.setControl(&control->_obj(), control);
328 template<
class... Args>
329 SharedControl_obj(Alloc&& a, Args&&... args) : _alloc(move(a)) {
new (&_storage) T(forward<Args>(args)...); }
330 virtual void finalize() { _obj().~T(); unrefWeak(); }
331 virtual void destroy() {
auto a = move(_alloc);
delete_(
this, a); }
332 T& _obj() {
return reinterpret_cast<T&
>(_storage); }
342 template<
class T,
class Alloc,
class... Args,
typename mt::disable_if<mt::is_base_of<priv::SharedObj_tag, T>::value,
int>::type=0>
346 template<
class T,
class Alloc,
class... Args,
typename std::enable_if<mt::is_base_of<priv::SharedObj_tag, T>::value,
int>::type=0>
354 template<
class T,
class U>
357 template<
class T,
class U>
360 template<
class T,
class U>
377 class WeakPtr : priv::SharedControlPtr<WeakPtr<T>, T>
379 typedef priv::SharedControlPtr<WeakPtr<T>, T> ControlPtr;
403 void set(nullptr_t) { setControl(static_cast<T*>(
nullptr),
nullptr); }
409 int refCount()
const {
if (_ptr)
return getControl().count();
return 0; }
411 bool expired()
const {
return refCount() == 0; }
415 void setControl(U* ptr, priv::SharedControl* control)
417 if (ptr) control->refWeak();
418 T* oldPtr = _ptr; priv::SharedControl* oldControl = this->_control();
419 _ptr = ptr; this->_control(control);
420 if (oldPtr) oldControl->unrefWeak();
423 priv::SharedControl& getControl()
const {
assert(this->_control());
return *this->_control(); }
~SharedPtr()
Definition: SharedPtr.h:225
SharedPtr< T > dynamic_pointer_cast(const SharedPtr< U > &rhs)
Definition: SharedPtr.h:358
SharedPtr(SharedPtr &&ptr)
Transfer ownership out of shared pointer, leaving it null.
Definition: SharedPtr.h:213
void set(nullptr_t)
Set to null, release reference.
Definition: SharedPtr.h:403
WeakPtr()
Definition: SharedPtr.h:385
Version of std::is_base_of that removes reference qualifiers before testing.
Definition: Meta.h:69
WeakPtr & operator=(const SharedPtr< U > &rhs)
Definition: SharedPtr.h:400
friend bool operator!=(nullptr_t, const SharedPtr &rhs)
Definition: SharedPtr.h:255
bool operator>(const String &lhs, const String &rhs)
Definition: String.h:148
Combined intrusive/non-intrusive smart pointer. Can reference and share any object automatically...
Definition: SharedPtr.h:175
void set(nullptr_t)
Definition: SharedPtr.h:276
bool operator!=(nullptr_t) const
Definition: SharedPtr.h:253
SharedPtr(const SharedPtr &ptr)
Reference the object pointed to by another shared pointer.
Definition: SharedPtr.h:209
Ref_< Elem >::type Ref
Definition: SharedPtr.h:193
Inherit to declare that class is not copyable.
Definition: Meta.h:286
SharedPtr< T > const_pointer_cast(const SharedPtr< U > &rhs)
Definition: SharedPtr.h:361
SharedPtr< T > lock() const
Acquire access to object. Shared ptr prevents object from being destroyed while in use...
Definition: SharedPtr.h:406
void delete_(T *&p)
Destruct object, free memory and set pointer to null.
Definition: Allocator.h:75
~WeakPtr()
Definition: SharedPtr.h:394
SharedPtr< T > alloc_shared(Alloc &&a, Args &&...args)
Create a shared ptr to an object of type T constructed with args. The object and the internal control...
Definition: SharedPtr.h:343
int refCount() const
Get number of shared references to the object.
Definition: SharedPtr.h:279
SharedPtr(SharedPtr< U > &&ptr)
Definition: SharedPtr.h:215
T * get() const
Get the raw pointer to the object.
Definition: SharedPtr.h:262
size_t operator()(const honey::SharedPtr< T > &val) const
Definition: SharedPtr.h:438
Reference-counted object for intrusive shared pointers.
Definition: SharedPtr.h:93
SharedPtr & operator=(SharedPtr &&rhs)
Definition: SharedPtr.h:230
Ref operator*() const
Definition: SharedPtr.h:258
SharedPtr< T > static_pointer_cast(const SharedPtr< U > &rhs)
Definition: SharedPtr.h:355
bool unique() const
Check whether this is the only shared reference to the object.
Definition: SharedPtr.h:281
bool operator<(const String &lhs, const String &rhs)
Definition: String.h:145
SharedPtr(UniquePtr< U, Fin > &&ptr)
Transfer ownership out of unique pointer, leaving it null.
Definition: SharedPtr.h:223
WeakPtr(const WeakPtr &rhs)
Definition: SharedPtr.h:390
SharedPtr< T > alloc_shared(Alloc &&a, Args &&...args)
Specializaton for intrusive pointers, simply allocates T and constructs with args.
Definition: SharedPtr.h:347
SharedPtr(U *ptr, Fin &&f=Fin(), Alloc &&a=Alloc())
Reference an object with finalizer and internal control block allocator. For non-intrusive pointers o...
Definition: SharedPtr.h:206
bool expired() const
Check whether the object has already been destroyed.
Definition: SharedPtr.h:411
T Elem
Definition: SharedPtr.h:192
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
std::enable_if< std::is_default_constructible< Com >::value &&!std::is_abstract< Com >::value, Component & >::type create()
Called by registry to create a component. May be specialized for a component type.
Definition: Component.h:75
SharedObj(Alloc &&a=Alloc()) debug_if(
Construct with allocator that is called to deallocate this shared object when all references have bee...
Definition: SharedPtr.h:101
SharedPtr(const SharedPtr< U > &ptr)
Definition: SharedPtr.h:211
int refCount() const
Get strong reference (SharedPtr) count.
Definition: SharedPtr.h:409
bool operator!=(const SharedPtr< U > &rhs) const
Definition: SharedPtr.h:242
SharedPtr & operator=(const SharedPtr< U > &rhs)
Definition: SharedPtr.h:229
SharedPtr(const WeakPtr< U > &ptr)
Lock a weak pointer to get access to its object. Shared ptr will be null if the object has already be...
Definition: SharedPtr.h:219
T * operator->() const
Definition: SharedPtr.h:257
#define debug_if(...)
Evaluate expression in debug mode only, does nothing in final mode.
Definition: Debug.h:30
void finalize()
Destroys object. Called when strong reference count reaches 0. May be overridden to prevent destructi...
Definition: SharedPtr.h:110
WeakPtr & operator=(const WeakPtr< U > &rhs)
Definition: SharedPtr.h:398
SharedPtr< T > make_shared(Args &&...args)
alloc_shared() using T::Allocator if available, otherwise std::allocator
Definition: SharedPtr.h:351
SharedPtr & operator=(const SharedPtr &rhs)
Definition: SharedPtr.h:227
NoCopy & operator=(const NoCopy &)=delete
SharedPtr & operator=(SharedPtr< U > &&rhs)
Definition: SharedPtr.h:232
WeakPtr & operator=(const WeakPtr &rhs)
Definition: SharedPtr.h:396
bool operator==(const String &lhs, const String &rhs)
Definition: String.h:139
friend bool operator==(nullptr_t, const SharedPtr &rhs)
Definition: SharedPtr.h:254
SharedPtr & operator=(UniquePtr< U, Fin > &&rhs)
Definition: SharedPtr.h:235
bool operator==(nullptr_t) const
Definition: SharedPtr.h:252
WeakPtr(const SharedPtr< U > &rhs)
Must construct from a shared pointer.
Definition: SharedPtr.h:389
bool operator>=(const SharedPtr< U > &rhs) const
Definition: SharedPtr.h:250
Point to a shared object without holding a reference. The object is accessible through a lock...
Definition: SharedPtr.h:165
void set(U *ptr, Fin &&f=Fin(), Alloc &&a=Alloc())
Dereference the current object and reference a new object, with finalizer and internal control block ...
Definition: SharedPtr.h:269
SharedPtr()
Definition: SharedPtr.h:195
Pointer to a unique, non-shared, object. Finalizer is run upon destruction (deletes object by default...
Definition: SharedPtr.h:164
WeakPtr(const WeakPtr< U > &rhs)
Definition: SharedPtr.h:392
WeakPtr(nullptr_t)
Definition: SharedPtr.h:386
SharedPtr(nullptr_t)
Definition: SharedPtr.h:196
std::allocator< T > type
Definition: Allocator.h:152
Global Honeycomb namespace.
void set(U *ptr)
Dereference the current object and reference a new object. For intrusive pointers only...
Definition: SharedPtr.h:266
SharedPtr(U *ptr)
Reference an object, allowing for implicit construction. For intrusive pointers only.
Definition: SharedPtr.h:200
bool operator==(const SharedPtr< U > &rhs) const
Definition: SharedPtr.h:240