Optional Two-phase heap tracing
[hiphop-php.git] / hphp / util / default-ptr.h
bloba26169dca7d10dbcd8e225557ceb55f735df5c11
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_DEFAULT_PTR_H_
18 #define incl_HPHP_DEFAULT_PTR_H_
20 #include <cstddef>
21 #include <utility>
23 namespace HPHP {
24 ///////////////////////////////////////////////////////////////////////////////
27 * Pointer which can be safely const-dereferenced when null to yield a
28 * default-constructed value.
30 template <class T>
31 struct default_ptr {
33 * Constructors.
35 default_ptr() : m_p{fallback()} {}
37 /* implicit */ default_ptr(std::nullptr_t) {}
39 /* implicit */ default_ptr(T* p) : m_p{p ? p : fallback()} {}
42 * Thread-safe allocation.
44 T* ensureAllocated() {
45 if (auto p = raw()) return p;
46 auto ptr = new T();
47 T* expected = fallback();
48 if (!m_p.compare_exchange_strong(
49 expected, ptr, std::memory_order_relaxed)) {
50 // Already set by someone else, use theirs.
51 delete ptr;
52 return expected;
53 } else {
54 return ptr;
59 * Assignments.
61 default_ptr& operator=(std::nullptr_t /*p*/) {
62 m_p.store(fallback(), std::memory_order_relaxed);
63 return *this;
65 default_ptr& operator=(T* p) {
66 m_p.store(p ? p : fallback(), std::memory_order_relaxed);
67 return *this;
71 * Observers.
73 const T* get() const {
74 return m_p.load(std::memory_order_relaxed);
76 const T& operator*() const {
77 return *get();
79 const T* operator->() const {
80 return get();
83 T* raw() const {
84 auto p = m_p.load(std::memory_order_relaxed);
85 return p == &s_default ? nullptr : p;
87 explicit operator bool() const {
88 return raw();
92 * Modifiers.
94 void reset(T* p = nullptr) {
95 operator=(p);
98 private:
100 * Internals.
102 static T* fallback() {
103 return const_cast<T*>(&s_default);
106 private:
107 std::atomic<T*> m_p{const_cast<T*>(&s_default)};
108 static const T s_default;
111 template <class T>
112 const T default_ptr<T>::s_default;
114 ///////////////////////////////////////////////////////////////////////////////
117 #endif // incl_HPHP_DEFAULT_PTR_H_