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