Fix ServiceInterceptor::getValueAsType
[hiphop-php.git] / hphp / util / default-ptr.h
blobdbcb9cae138c20dfa5db9be8eb5e6f151f3dfc2b
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 #pragma once
19 #include <cstddef>
20 #include <utility>
22 namespace HPHP {
23 ///////////////////////////////////////////////////////////////////////////////
26 * Pointer which can be safely const-dereferenced when null to yield a
27 * default-constructed value.
29 template <class T>
30 struct default_ptr {
32 * Constructors.
34 default_ptr() : m_p{fallback()} {}
36 /* implicit */ default_ptr(std::nullptr_t) {}
38 /* implicit */ default_ptr(T* p) : m_p{p ? p : fallback()} {}
41 * Thread-safe allocation.
43 T* ensureAllocated() {
44 if (auto p = raw()) return p;
45 auto ptr = new T();
46 T* expected = fallback();
47 if (!m_p.compare_exchange_strong(
48 expected, ptr, std::memory_order_acq_rel)) {
49 // Already set by someone else, use theirs.
50 delete ptr;
51 return expected;
52 } else {
53 return ptr;
58 * Assignments.
60 default_ptr& operator=(std::nullptr_t /*p*/) {
61 m_p.store(fallback(), std::memory_order_release);
62 return *this;
64 default_ptr& operator=(T* p) {
65 m_p.store(p ? p : fallback(), std::memory_order_release);
66 return *this;
70 * Observers.
72 const T* get() const {
73 return m_p.load(std::memory_order_acquire);
75 const T& operator*() const {
76 return *get();
78 const T* operator->() const {
79 return get();
82 T* raw() const {
83 auto p = m_p.load(std::memory_order_acquire);
84 return p == &s_default ? nullptr : p;
86 explicit operator bool() const {
87 return raw();
91 * Modifiers.
93 void reset(T* p = nullptr) {
94 operator=(p);
97 private:
99 * Internals.
101 static T* fallback() {
102 return const_cast<T*>(&s_default);
105 private:
106 std::atomic<T*> m_p{const_cast<T*>(&s_default)};
107 static const T s_default;
110 template <class T>
111 const T default_ptr<T>::s_default;
113 ///////////////////////////////////////////////////////////////////////////////