|
|
bf6839 |
#ifndef HANDLE_H
|
|
|
bf6839 |
#define HANDLE_H
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
#include <cassert></cassert>
|
|
|
bf6839 |
|
|
|
bf6839 |
#include <atomic></atomic>
|
|
|
bf6839 |
#include <utility></utility>
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
class Shared;
|
|
|
98bb38 |
template<typename t=""> class THandle;</typename>
|
|
|
98bb38 |
template<typename t=""> class TWeakHandle;</typename>
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
class Counter {
|
|
|
bf6839 |
private:
|
|
|
bf6839 |
friend class Shared;
|
|
|
bf6839 |
friend class HandleBase;
|
|
|
bf6839 |
friend class WeakHandleBase;
|
|
|
bf6839 |
|
|
|
bf6839 |
typedef unsigned int Type;
|
|
|
bf6839 |
std::atomic<type> refCount;</type>
|
|
|
bf6839 |
std::atomic<type> ptrRefCount;</type>
|
|
|
bf6839 |
Shared* pointer;
|
|
|
bf6839 |
|
|
|
bf6839 |
inline explicit Counter(Shared &shared): refCount(1), ptrRefCount(0), pointer(&shared) { }
|
|
|
bf6839 |
inline ~Counter() { assert(!refCount && !ptrRefCount); }
|
|
|
541903 |
Counter& operator=(const Counter&) = delete;
|
|
|
bf6839 |
};
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
class Shared {
|
|
|
98bb38 |
public:
|
|
|
98bb38 |
typedef THandle<shared> Handle;</shared>
|
|
|
98bb38 |
|
|
|
bf6839 |
private:
|
|
|
bf6839 |
friend class HandleBase;
|
|
|
bf6839 |
friend class WeakHandleBase;
|
|
|
541903 |
Counter * const counter;
|
|
|
bf6839 |
|
|
|
541903 |
Shared(const Shared&) = delete;
|
|
|
541903 |
Shared& operator=(const Shared&) = delete;
|
|
|
bf6839 |
public:
|
|
|
bf6839 |
inline Shared(): counter(new Counter(*this)) { }
|
|
|
bf6839 |
virtual ~Shared();
|
|
|
bf6839 |
};
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
class WeakHandleBase {
|
|
|
bf6839 |
private:
|
|
|
bf6839 |
friend class HandleBase;
|
|
|
bf6839 |
Counter* counter;
|
|
|
bf6839 |
|
|
|
bf6839 |
inline void set(Counter* counter) {
|
|
|
bf6839 |
if (this->counter == counter) return;
|
|
|
bf6839 |
if (counter) counter->refCount++;
|
|
|
bf6839 |
if (this->counter && !--this->counter->refCount) delete this->counter;
|
|
|
bf6839 |
this->counter = counter;
|
|
|
bf6839 |
}
|
|
|
bf6839 |
|
|
|
bf6839 |
protected:
|
|
|
bf6839 |
inline WeakHandleBase(): counter() { }
|
|
|
98bb38 |
inline void set(Shared* pointer) { set(pointer ? pointer->counter : nullptr); }
|
|
|
98bb38 |
inline void set(const WeakHandleBase &other) { set(other.counter); }
|
|
|
98bb38 |
inline void swap(WeakHandleBase &other) { std::swap(counter, other.counter); }
|
|
|
bf6839 |
|
|
|
bf6839 |
public:
|
|
|
bf6839 |
inline ~WeakHandleBase()
|
|
|
bf6839 |
{ reset(); }
|
|
|
bf6839 |
inline void reset()
|
|
|
bf6839 |
{ return set((Counter*)nullptr); }
|
|
|
bf6839 |
inline bool operator<(const WeakHandleBase &other) const
|
|
|
bf6839 |
{ return counter < other.counter; }
|
|
|
bf6839 |
};
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
class HandleBase {
|
|
|
bf6839 |
private:
|
|
|
bf6839 |
Shared *pointer;
|
|
|
bf6839 |
|
|
|
bf6839 |
protected:
|
|
|
bf6839 |
inline HandleBase(): pointer() { }
|
|
|
bf6839 |
|
|
|
bf6839 |
inline void set(Shared *pointer) {
|
|
|
bf6839 |
if (this->pointer == pointer) return;
|
|
|
bf6839 |
if (pointer) pointer->counter->ptrRefCount++;
|
|
|
bf6839 |
if (this->pointer && !--this->pointer->counter->ptrRefCount) delete this->pointer;
|
|
|
bf6839 |
this->pointer = pointer;
|
|
|
bf6839 |
}
|
|
|
bf6839 |
|
|
|
bf6839 |
inline void set(const WeakHandleBase &weak) {
|
|
|
bf6839 |
Counter *counter = weak.counter;
|
|
|
bf6839 |
if (!counter) { set((Shared*)nullptr); return; }
|
|
|
bf6839 |
if (pointer && pointer->counter == counter) return;
|
|
|
bf6839 |
|
|
|
bf6839 |
Shared *pointer = nullptr;
|
|
|
bf6839 |
Counter::Type cnt = counter->refCount;
|
|
|
bf6839 |
while(cnt)
|
|
|
bf6839 |
if (counter->ptrRefCount.compare_exchange_weak(cnt, cnt+1))
|
|
|
bf6839 |
{ pointer = counter->pointer; break; }
|
|
|
bf6839 |
|
|
|
bf6839 |
if (this->pointer && !--this->pointer->counter->ptrRefCount) delete this->pointer;
|
|
|
bf6839 |
this->pointer = pointer;
|
|
|
bf6839 |
}
|
|
|
bf6839 |
|
|
|
bf6839 |
inline void swap(HandleBase &other) { std::swap(pointer, other.pointer); }
|
|
|
bf6839 |
|
|
|
bf6839 |
inline Shared* get() const
|
|
|
bf6839 |
{ return pointer; }
|
|
|
bf6839 |
|
|
|
bf6839 |
public:
|
|
|
bf6839 |
inline ~HandleBase()
|
|
|
bf6839 |
{ reset(); }
|
|
|
bf6839 |
|
|
|
bf6839 |
inline void reset()
|
|
|
bf6839 |
{ return set((Shared*)nullptr); }
|
|
|
bf6839 |
inline operator bool() const
|
|
|
bf6839 |
{ return pointer; }
|
|
|
bf6839 |
inline bool operator<(const HandleBase &other) const
|
|
|
bf6839 |
{ return pointer < other.pointer; }
|
|
|
bf6839 |
|
|
|
bf6839 |
inline bool operator==(const HandleBase &other) const
|
|
|
bf6839 |
{ return pointer == other.pointer; }
|
|
|
bf6839 |
inline bool operator==(const Shared *pointer) const
|
|
|
bf6839 |
{ return this->pointer == pointer; }
|
|
|
bf6839 |
inline friend bool operator==(const Shared *pointer, const HandleBase &handle)
|
|
|
bf6839 |
{ return pointer == handle.pointer; }
|
|
|
bf6839 |
|
|
|
bf6839 |
inline bool operator!=(const HandleBase &other) const
|
|
|
bf6839 |
{ return pointer != other.pointer; }
|
|
|
bf6839 |
inline bool operator!=(const Shared *pointer) const
|
|
|
bf6839 |
{ return this->pointer != pointer; }
|
|
|
bf6839 |
inline friend bool operator!=(const Shared *pointer, const HandleBase &handle)
|
|
|
bf6839 |
{ return pointer != handle.pointer; }
|
|
|
bf6839 |
};
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
template<typename t=""></typename>
|
|
|
98bb38 |
class TWeakHandle: public WeakHandleBase {
|
|
|
bf6839 |
public:
|
|
|
bf6839 |
typedef T Type;
|
|
|
98bb38 |
typedef THandle<type> Handle;</type>
|
|
|
bf6839 |
|
|
|
bf6839 |
private:
|
|
|
bf6839 |
inline void typeChecker(const Type*) { }
|
|
|
bf6839 |
|
|
|
bf6839 |
public:
|
|
|
98bb38 |
inline TWeakHandle() { }
|
|
|
98bb38 |
inline TWeakHandle(const std::nullptr_t) { }
|
|
|
98bb38 |
inline TWeakHandle(TWeakHandle &&other) { WeakHandleBase::swap(other); }
|
|
|
98bb38 |
inline TWeakHandle(const TWeakHandle &other) { WeakHandleBase::set(other); }
|
|
|
98bb38 |
inline explicit TWeakHandle(const Handle &handle) { WeakHandleBase::set(handle.pointer()); }
|
|
|
98bb38 |
|
|
|
98bb38 |
inline TWeakHandle& operator=(TWeakHandle &&other)
|
|
|
bf6839 |
{ WeakHandleBase::swap(other); return *this; }
|
|
|
98bb38 |
inline TWeakHandle& operator=(const TWeakHandle &other)
|
|
|
bf6839 |
{ WeakHandleBase::set(other); return *this; }
|
|
|
98bb38 |
inline TWeakHandle& operator=(const Handle &handle)
|
|
|
bf6839 |
{ WeakHandleBase::set(handle.pointer()); return *this; }
|
|
|
bf6839 |
|
|
|
98bb38 |
inline void swap(TWeakHandle &other)
|
|
|
bf6839 |
{ WeakHandleBase::swap(other); return *this; }
|
|
|
bf6839 |
|
|
|
bf6839 |
template<typename tt=""></typename>
|
|
|
98bb38 |
inline operator TWeakHandle<tt>&()</tt>
|
|
|
98bb38 |
{ typeChecker((TT*)nullptr); return *reinterpret_cast<tweakhandle<tt>*>(this); }</tweakhandle<tt>
|
|
|
bf6839 |
template<typename tt=""></typename>
|
|
|
98bb38 |
inline operator const TWeakHandle<tt>&() const</tt>
|
|
|
98bb38 |
{ typeChecker((TT*)nullptr); return *reinterpret_cast<const tweakhandle<tt="">*>(this); }</const>
|
|
|
bf6839 |
};
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
template<typename t=""></typename>
|
|
|
98bb38 |
class THandle: public HandleBase {
|
|
|
bf6839 |
public:
|
|
|
bf6839 |
typedef T Type;
|
|
|
98bb38 |
typedef TWeakHandle<type> Weak;</type>
|
|
|
bf6839 |
|
|
|
bf6839 |
private:
|
|
|
bf6839 |
inline void typeChecker(const Type*) { }
|
|
|
bf6839 |
|
|
|
bf6839 |
public:
|
|
|
98bb38 |
inline THandle() { }
|
|
|
98bb38 |
inline THandle(const std::nullptr_t) { }
|
|
|
98bb38 |
inline THandle(THandle &&other) { HandleBase::swap(other); }
|
|
|
98bb38 |
inline THandle(const THandle &other) { HandleBase::set(other.get()); }
|
|
|
98bb38 |
inline explicit THandle(const Weak &weak) { HandleBase::set(weak); }
|
|
|
98bb38 |
inline explicit THandle(Type *pointer) { HandleBase::set(pointer); }
|
|
|
98bb38 |
|
|
|
98bb38 |
inline THandle& operator=(THandle &&other)
|
|
|
bf6839 |
{ HandleBase::swap(other); return *this; }
|
|
|
98bb38 |
inline THandle& operator=(const THandle &other)
|
|
|
bf6839 |
{ HandleBase::set(other.get()); return *this; }
|
|
|
98bb38 |
inline THandle& operator=(const Weak &weak)
|
|
|
bf6839 |
{ HandleBase::set(weak); return *this; }
|
|
|
98bb38 |
inline THandle& operator=(Type *pointer)
|
|
|
bf6839 |
{ HandleBase::set(pointer); return *this; }
|
|
|
bf6839 |
|
|
|
98bb38 |
inline void swap(THandle &other)
|
|
|
bf6839 |
{ HandleBase::swap(other); return *this; }
|
|
|
bf6839 |
|
|
|
bf6839 |
inline Type* pointer() const { return (Type*)HandleBase::get(); }
|
|
|
2a209b |
inline Type* operator->() const { assert(pointer()); return pointer(); }
|
|
|
2a209b |
inline Type& operator*() const { assert(pointer()); return *pointer(); }
|
|
|
bf6839 |
|
|
|
bf6839 |
template<typename tt=""></typename>
|
|
|
98bb38 |
inline operator THandle<tt>&()</tt>
|
|
|
98bb38 |
{ typeChecker((TT*)nullptr); return *reinterpret_cast<thandle<tt>*>(this); }</thandle<tt>
|
|
|
bf6839 |
template<typename tt=""></typename>
|
|
|
98bb38 |
inline operator const THandle<tt>&() const</tt>
|
|
|
98bb38 |
{ typeChecker((TT*)nullptr); return *reinterpret_cast<const thandle<tt="">*>(this); }</const>
|
|
|
bf6839 |
};
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
|
|
|
bf6839 |
#endif
|