summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/wavm/Include/WAVM/Inline/IntrusiveSharedPtr.h
blob: 7f1d09d393f13984a1a0d4a59926e6c8334d71dd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#pragma once

namespace WAVM {
	// A smart pointer that uses an intrusive reference counter.
	// Needs Pointee to define memory functions to manipulate the reference count:
	//   void addRef();
	//   void removeRef();
	template<typename Pointee> struct IntrusiveSharedPtr
	{
		// Constructors/destructor
		constexpr IntrusiveSharedPtr() : value(nullptr) {}
		IntrusiveSharedPtr(Pointee* inValue)
		{
			value = inValue;
			if(value) { value->addRef(); }
		}
		IntrusiveSharedPtr(const IntrusiveSharedPtr<Pointee>& inCopy)
		{
			value = inCopy.value;
			if(value) { value->addRef(); }
		}
		IntrusiveSharedPtr(IntrusiveSharedPtr<Pointee>&& inMove) noexcept
		{
			value = inMove.value;
			inMove.value = nullptr;
		}

		~IntrusiveSharedPtr()
		{
			if(value) { value->removeRef(); }
		}

		// Adopt a raw pointer: coerces the pointer to an IntrusiveSharedPtr without calling addRef
		// or removeRef.
		static IntrusiveSharedPtr<Pointee> adopt(Pointee*&& inValue)
		{
			IntrusiveSharedPtr<Pointee> result(adoptConstructorSelector, inValue);
			inValue = nullptr;
			return result;
		}

		// Assignment operators
		void operator=(Pointee* inValue)
		{
			auto oldValue = value;
			value = inValue;
			if(value) { value->addRef(); }
			if(oldValue) { oldValue->removeRef(); }
		}
		void operator=(const IntrusiveSharedPtr<Pointee>& inCopy)
		{
			auto oldValue = value;
			value = inCopy.value;
			if(value) { value->addRef(); }
			if(oldValue) { oldValue->removeRef(); }
		}
		void operator=(IntrusiveSharedPtr<Pointee>&& inMove) noexcept
		{
			auto oldValue = value;
			value = inMove.value;
			inMove.value = nullptr;
			if(oldValue) { oldValue->removeRef(); }
		}

		// Accessors
		constexpr operator Pointee*() const { return value; }
		constexpr Pointee& operator*() const { return *value; }
		constexpr Pointee* operator->() const { return value; }

	private:
		Pointee* value;

		enum AdoptConstructorSelector
		{
			adoptConstructorSelector
		};

		constexpr IntrusiveSharedPtr(AdoptConstructorSelector, Pointee* inValue) : value(inValue) {}
	};
}