1
+ #if !defined(CODEQL_MEMORY_H)
2
+ #define CODEQL_MEMORY_H
3
+
4
+ namespace std {
5
+ namespace detail {
6
+ template <typename T>
7
+ class compressed_pair_element {
8
+ T element;
9
+
10
+ public:
11
+ compressed_pair_element () = default ;
12
+ compressed_pair_element (const T& t) : element(t) {}
13
+
14
+ T& get () { return element; }
15
+
16
+ const T& get () const { return element; }
17
+ };
18
+
19
+ template <typename T, typename U>
20
+ struct compressed_pair : private compressed_pair_element <T>, private compressed_pair_element<U> {
21
+ compressed_pair () = default ;
22
+ compressed_pair (T& t) : compressed_pair_element<T>(t), compressed_pair_element<U>() {}
23
+ compressed_pair (const compressed_pair&) = delete ;
24
+ compressed_pair (compressed_pair<T, U>&&) noexcept = default ;
25
+
26
+ T& first () { return static_cast <compressed_pair_element<T>&>(*this ).get (); }
27
+ U& second () { return static_cast <compressed_pair_element<U>&>(*this ).get (); }
28
+
29
+ const T& first () const { return static_cast <const compressed_pair_element<T>&>(*this ).get (); }
30
+ const U& second () const { return static_cast <const compressed_pair_element<U>&>(*this ).get (); }
31
+ };
32
+ }
33
+
34
+ template <class T >
35
+ struct default_delete {
36
+ void operator ()(T* ptr) const { delete ptr; }
37
+ };
38
+
39
+ template <class T >
40
+ struct default_delete <T[]> {
41
+ template <class U >
42
+ void operator ()(U* ptr) const { delete[] ptr; }
43
+ };
44
+
45
+ template <class T , class Deleter = default_delete<T> >
46
+ class unique_ptr {
47
+ private:
48
+ detail::compressed_pair<T*, Deleter> data;
49
+ public:
50
+ constexpr unique_ptr () noexcept {}
51
+ explicit unique_ptr (T* ptr) noexcept : data(ptr) {}
52
+ unique_ptr (const unique_ptr& ptr) = delete ;
53
+ unique_ptr (unique_ptr&& ptr) noexcept = default ;
54
+
55
+ unique_ptr& operator =(unique_ptr&& ptr) noexcept = default ;
56
+
57
+ T& operator *() const { return *get (); }
58
+ T* operator ->() const noexcept { return get (); }
59
+
60
+ T* get () const noexcept { return data.first (); }
61
+ T* release () noexcept {
62
+ Deleter& d = data.second ();
63
+ d (data.first ());
64
+ data.first () = nullptr ;
65
+ }
66
+
67
+ ~unique_ptr () {
68
+ Deleter& d = data.second ();
69
+ d (data.first ());
70
+ }
71
+ };
72
+
73
+ template <typename T, class ... Args> unique_ptr<T> make_unique (Args&&... args) {
74
+ return unique_ptr<T>(new T (args...)); // std::forward calls elided for simplicity.
75
+ }
76
+
77
+ class ctrl_block {
78
+ unsigned uses;
79
+
80
+ public:
81
+ ctrl_block () : uses(1 ) {}
82
+
83
+ void inc () { ++uses; }
84
+ bool dec () { return --uses == 0 ; }
85
+
86
+ virtual void destroy () = 0;
87
+ virtual ~ctrl_block () {}
88
+ };
89
+
90
+ template <typename T, class Deleter = default_delete<T> >
91
+ struct ctrl_block_impl : public ctrl_block {
92
+ T* ptr;
93
+ Deleter d;
94
+
95
+ ctrl_block_impl (T* ptr, Deleter d) : ptr(ptr), d(d) {}
96
+ virtual void destroy () override { d (ptr); }
97
+ };
98
+
99
+ template <class T >
100
+ class shared_ptr {
101
+ private:
102
+ ctrl_block* ctrl;
103
+ T* ptr;
104
+
105
+ void dec () {
106
+ if (ctrl->dec ()) {
107
+ ctrl->destroy ();
108
+ delete ctrl;
109
+ }
110
+ }
111
+
112
+ void inc () {
113
+ ctrl->inc ();
114
+ }
115
+
116
+ public:
117
+ constexpr shared_ptr () noexcept = default;
118
+ shared_ptr (T* ptr) : ctrl(new ctrl_block_impl<T>(ptr, default_delete<T>())) {}
119
+ shared_ptr (const shared_ptr& s) noexcept : ptr(s.ptr), ctrl(s.ctrl) {
120
+ inc ();
121
+ }
122
+ shared_ptr (shared_ptr&& s) noexcept = default ;
123
+ shared_ptr (unique_ptr<T>&& s) : shared_ptr(s.release()) {
124
+ }
125
+ T* operator ->() const { return ptr; }
126
+
127
+ T& operator *() const { return *ptr; }
128
+
129
+ ~shared_ptr () { dec (); }
130
+ };
131
+
132
+ template <typename T, class ... Args> shared_ptr<T> make_shared (Args&&... args) {
133
+ return shared_ptr<T>(new T (args...)); // std::forward calls elided for simplicity.
134
+ }
135
+ }
136
+
137
+ #endif
0 commit comments