added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / util / bind_ptr.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_UTIL_BIND_PTR_HPP
20 #define REALM_UTIL_BIND_PTR_HPP
21
22 #include <algorithm>
23 #include <atomic>
24 #include <ostream>
25 #include <utility>
26
27 #include <realm/util/features.h>
28 #include <realm/util/assert.hpp>
29
30
31 namespace realm {
32 namespace util {
33
34 class bind_ptr_base {
35 public:
36     struct adopt_tag {
37     };
38 };
39
40
41 /// A generic intrusive smart pointer that binds itself explicitely to
42 /// the target object.
43 ///
44 /// This class is agnostic towards what 'binding' means for the target
45 /// object, but a common use is 'reference counting'. See RefCountBase
46 /// for an example of that.
47 ///
48 /// This smart pointer implementation assumes that the target object
49 /// destructor never throws.
50 template <class T>
51 class bind_ptr : public bind_ptr_base {
52 public:
53     constexpr bind_ptr() noexcept
54         : m_ptr(nullptr)
55     {
56     }
57     ~bind_ptr() noexcept
58     {
59         unbind();
60     }
61
62     explicit bind_ptr(T* p) noexcept
63     {
64         bind(p);
65     }
66     template <class U>
67     explicit bind_ptr(U* p) noexcept
68     {
69         bind(p);
70     }
71
72     bind_ptr(T* p, adopt_tag) noexcept
73     {
74         m_ptr = p;
75     }
76     template <class U>
77     bind_ptr(U* p, adopt_tag) noexcept
78     {
79         m_ptr = p;
80     }
81
82     // Copy construct
83     bind_ptr(const bind_ptr& p) noexcept
84     {
85         bind(p.m_ptr);
86     }
87     template <class U>
88     bind_ptr(const bind_ptr<U>& p) noexcept
89     {
90         bind(p.m_ptr);
91     }
92
93     // Copy assign
94     bind_ptr& operator=(const bind_ptr& p) noexcept
95     {
96         bind_ptr(p).swap(*this);
97         return *this;
98     }
99     template <class U>
100     bind_ptr& operator=(const bind_ptr<U>& p) noexcept
101     {
102         bind_ptr(p).swap(*this);
103         return *this;
104     }
105
106     // Move construct
107     bind_ptr(bind_ptr&& p) noexcept
108         : m_ptr(p.release())
109     {
110     }
111     template <class U>
112     bind_ptr(bind_ptr<U>&& p) noexcept
113         : m_ptr(p.release())
114     {
115     }
116
117     // Move assign
118     bind_ptr& operator=(bind_ptr&& p) noexcept
119     {
120         bind_ptr(std::move(p)).swap(*this);
121         return *this;
122     }
123     template <class U>
124     bind_ptr& operator=(bind_ptr<U>&& p) noexcept
125     {
126         bind_ptr(std::move(p)).swap(*this);
127         return *this;
128     }
129
130     //@{
131     // Comparison
132     template <class U>
133     bool operator==(const bind_ptr<U>&) const noexcept;
134
135     template <class U>
136     bool operator==(U*) const noexcept;
137
138     template <class U>
139     bool operator!=(const bind_ptr<U>&) const noexcept;
140
141     template <class U>
142     bool operator!=(U*) const noexcept;
143
144     template <class U>
145     bool operator<(const bind_ptr<U>&) const noexcept;
146
147     template <class U>
148     bool operator<(U*) const noexcept;
149
150     template <class U>
151     bool operator>(const bind_ptr<U>&) const noexcept;
152
153     template <class U>
154     bool operator>(U*) const noexcept;
155
156     template <class U>
157     bool operator<=(const bind_ptr<U>&) const noexcept;
158
159     template <class U>
160     bool operator<=(U*) const noexcept;
161
162     template <class U>
163     bool operator>=(const bind_ptr<U>&) const noexcept;
164
165     template <class U>
166     bool operator>=(U*) const noexcept;
167     //@}
168
169     // Dereference
170     T& operator*() const noexcept
171     {
172         return *m_ptr;
173     }
174     T* operator->() const noexcept
175     {
176         return m_ptr;
177     }
178
179     explicit operator bool() const noexcept
180     {
181         return m_ptr != 0;
182     }
183
184     T* get() const noexcept
185     {
186         return m_ptr;
187     }
188     void reset() noexcept
189     {
190         bind_ptr().swap(*this);
191     }
192     void reset(T* p) noexcept
193     {
194         bind_ptr(p).swap(*this);
195     }
196     template <class U>
197     void reset(U* p) noexcept
198     {
199         bind_ptr(p).swap(*this);
200     }
201
202     T* release() noexcept
203     {
204         T* const p = m_ptr;
205         m_ptr = nullptr;
206         return p;
207     }
208
209     void swap(bind_ptr& p) noexcept
210     {
211         std::swap(m_ptr, p.m_ptr);
212     }
213     friend void swap(bind_ptr& a, bind_ptr& b) noexcept
214     {
215         a.swap(b);
216     }
217
218 protected:
219     struct casting_move_tag {
220     };
221     template <class U>
222     bind_ptr(bind_ptr<U>* p, casting_move_tag) noexcept
223         : m_ptr(static_cast<T*>(p->release()))
224     {
225     }
226
227 private:
228     T* m_ptr;
229
230     void bind(T* p) noexcept
231     {
232         if (p)
233             p->bind_ptr();
234         m_ptr = p;
235     }
236     void unbind() noexcept
237     {
238         if (m_ptr)
239             m_ptr->unbind_ptr();
240     }
241
242     template <class>
243     friend class bind_ptr;
244 };
245
246
247 template <class C, class T, class U>
248 inline std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& out, const bind_ptr<U>& p)
249 {
250     out << static_cast<const void*>(p.get());
251     return out;
252 }
253
254
255 //@{
256 // Comparison
257 template <class T, class U>
258 bool operator==(T*, const bind_ptr<U>&) noexcept;
259 template <class T, class U>
260 bool operator!=(T*, const bind_ptr<U>&) noexcept;
261 template <class T, class U>
262 bool operator<(T*, const bind_ptr<U>&) noexcept;
263 template <class T, class U>
264 bool operator>(T*, const bind_ptr<U>&) noexcept;
265 template <class T, class U>
266 bool operator<=(T*, const bind_ptr<U>&) noexcept;
267 template <class T, class U>
268 bool operator>=(T*, const bind_ptr<U>&) noexcept;
269 //@}
270
271
272 /// Polymorphic convenience base class for reference counting objects.
273 ///
274 /// Together with bind_ptr, this class delivers simple instrusive
275 /// reference counting.
276 ///
277 /// \sa bind_ptr
278 class RefCountBase {
279 public:
280     RefCountBase() noexcept
281         : m_ref_count(0)
282     {
283     }
284     virtual ~RefCountBase() noexcept
285     {
286         REALM_ASSERT(m_ref_count == 0);
287     }
288
289     RefCountBase(const RefCountBase&) = delete;
290     RefCountBase(RefCountBase&&) = delete;
291
292     void operator=(const RefCountBase&) = delete;
293     void operator=(RefCountBase&&) = delete;
294
295 protected:
296     void bind_ptr() const noexcept
297     {
298         ++m_ref_count;
299     }
300     void unbind_ptr() const noexcept
301     {
302         if (--m_ref_count == 0)
303             delete this;
304     }
305
306 private:
307     mutable unsigned long m_ref_count;
308
309     template <class>
310     friend class bind_ptr;
311 };
312
313
314 /// Same as RefCountBase, but this one makes the copying of, and the
315 /// destruction of counted references thread-safe.
316 ///
317 /// \sa RefCountBase
318 /// \sa bind_ptr
319 class AtomicRefCountBase {
320 public:
321     AtomicRefCountBase() noexcept
322         : m_ref_count(0)
323     {
324     }
325     virtual ~AtomicRefCountBase() noexcept
326     {
327         REALM_ASSERT(m_ref_count == 0);
328     }
329
330     AtomicRefCountBase(const AtomicRefCountBase&) = delete;
331     AtomicRefCountBase(AtomicRefCountBase&&) = delete;
332
333     void operator=(const AtomicRefCountBase&) = delete;
334     void operator=(AtomicRefCountBase&&) = delete;
335
336 protected:
337     // FIXME: Operators ++ and -- as used below use
338     // std::memory_order_seq_cst. This can be optimized.
339     void bind_ptr() const noexcept
340     {
341         ++m_ref_count;
342     }
343     void unbind_ptr() const noexcept
344     {
345         if (--m_ref_count == 0) {
346             delete this;
347         }
348     }
349
350 private:
351     mutable std::atomic<unsigned long> m_ref_count;
352
353     template <class>
354     friend class bind_ptr;
355 };
356
357
358 // Implementation:
359
360 template <class T>
361 template <class U>
362 bool bind_ptr<T>::operator==(const bind_ptr<U>& p) const noexcept
363 {
364     return m_ptr == p.m_ptr;
365 }
366
367 template <class T>
368 template <class U>
369 bool bind_ptr<T>::operator==(U* p) const noexcept
370 {
371     return m_ptr == p;
372 }
373
374 template <class T>
375 template <class U>
376 bool bind_ptr<T>::operator!=(const bind_ptr<U>& p) const noexcept
377 {
378     return m_ptr != p.m_ptr;
379 }
380
381 template <class T>
382 template <class U>
383 bool bind_ptr<T>::operator!=(U* p) const noexcept
384 {
385     return m_ptr != p;
386 }
387
388 template <class T>
389 template <class U>
390 bool bind_ptr<T>::operator<(const bind_ptr<U>& p) const noexcept
391 {
392     return m_ptr < p.m_ptr;
393 }
394
395 template <class T>
396 template <class U>
397 bool bind_ptr<T>::operator<(U* p) const noexcept
398 {
399     return m_ptr < p;
400 }
401
402 template <class T>
403 template <class U>
404 bool bind_ptr<T>::operator>(const bind_ptr<U>& p) const noexcept
405 {
406     return m_ptr > p.m_ptr;
407 }
408
409 template <class T>
410 template <class U>
411 bool bind_ptr<T>::operator>(U* p) const noexcept
412 {
413     return m_ptr > p;
414 }
415
416 template <class T>
417 template <class U>
418 bool bind_ptr<T>::operator<=(const bind_ptr<U>& p) const noexcept
419 {
420     return m_ptr <= p.m_ptr;
421 }
422
423 template <class T>
424 template <class U>
425 bool bind_ptr<T>::operator<=(U* p) const noexcept
426 {
427     return m_ptr <= p;
428 }
429
430 template <class T>
431 template <class U>
432 bool bind_ptr<T>::operator>=(const bind_ptr<U>& p) const noexcept
433 {
434     return m_ptr >= p.m_ptr;
435 }
436
437 template <class T>
438 template <class U>
439 bool bind_ptr<T>::operator>=(U* p) const noexcept
440 {
441     return m_ptr >= p;
442 }
443
444 template <class T, class U>
445 bool operator==(T* a, const bind_ptr<U>& b) noexcept
446 {
447     return b == a;
448 }
449
450 template <class T, class U>
451 bool operator!=(T* a, const bind_ptr<U>& b) noexcept
452 {
453     return b != a;
454 }
455
456 template <class T, class U>
457 bool operator<(T* a, const bind_ptr<U>& b) noexcept
458 {
459     return b > a;
460 }
461
462 template <class T, class U>
463 bool operator>(T* a, const bind_ptr<U>& b) noexcept
464 {
465     return b < a;
466 }
467
468 template <class T, class U>
469 bool operator<=(T* a, const bind_ptr<U>& b) noexcept
470 {
471     return b >= a;
472 }
473
474 template <class T, class U>
475 bool operator>=(T* a, const bind_ptr<U>& b) noexcept
476 {
477     return b <= a;
478 }
479
480
481 } // namespace util
482 } // namespace realm
483
484 #endif // REALM_UTIL_BIND_PTR_HPP