Blame handle.h

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