2 +----------------------------------------------------------------------+
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_LOW_PTR_H_
18 #define incl_HPHP_LOW_PTR_H_
20 #include "hphp/util/low-ptr-def.h"
21 #include "hphp/util/assertions.h"
22 #include "hphp/util/portability.h"
24 #include <folly/Format.h>
30 #include <type_traits>
34 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
41 * Low memory pointer template.
43 template <class T
, class S
>
45 using storage_type
= typename
S::storage_type
;
52 /* implicit */ LowPtrImpl(T
* px
) : m_s
{to_low(px
)} {}
54 /* implicit */ LowPtrImpl(std::nullptr_t
/*px*/) : m_s
{ 0 } {}
56 LowPtrImpl(const LowPtrImpl
<T
, S
>& r
) : m_s
{S::get(r
.m_s
)} {}
58 LowPtrImpl(LowPtrImpl
<T
, S
>&& r
) : m_s
{S::get(r
.m_s
)} {
65 LowPtrImpl
& operator=(T
* px
) {
66 S::set(m_s
, to_low(px
));
70 LowPtrImpl
& operator=(std::nullptr_t
/*px*/) {
75 LowPtrImpl
& operator=(const LowPtrImpl
<T
, S
>& r
) {
76 S::set(m_s
, S::get(r
.m_s
));
80 template <typename Q
= S
>
81 typename
std::enable_if
<
82 std::is_move_assignable
<typename
Q::storage_type
>::value
,
84 >::type
operator=(LowPtrImpl
<T
, S
>&& r
) {
85 m_s
= std::move(r
.m_s
);
89 template <typename Q
= S
>
90 typename
std::enable_if
<
91 !std::is_move_assignable
<typename
Q::storage_type
>::value
,
93 >::type
operator=(LowPtrImpl
<T
, S
>&& r
) {
94 S::set(m_s
, S::get(r
.m_s
));
103 return reinterpret_cast<T
*>(S::get(m_s
));
106 T
& operator*() const {
110 T
* operator->() const {
114 /* implicit */ operator T
*() const {
118 explicit operator bool() const {
129 template <typename Q
= T
>
130 typename
std::enable_if
<
131 std::is_move_assignable
<typename
Q::storage_type
>::value
,
133 >::type
swap(LowPtrImpl
& r
) {
134 std::swap(m_s
, r
.m_s
);
137 template <typename Q
= T
>
138 typename
std::enable_if
<
139 !std::is_move_assignable
<typename
Q::storage_type
>::value
,
141 >::type
swap(LowPtrImpl
& r
) {
142 auto const tmp
= S::get(m_s
);
143 S::set(m_s
, S::get(r
.m_s
));
151 static bool is_low(T
* px
) {
152 typename
S::raw_type ones
= ~0;
153 auto ptr
= reinterpret_cast<uintptr_t>(px
);
154 return (ptr
& ones
) == ptr
;
157 static typename
S::raw_type
to_low(T
* px
) {
158 always_assert(is_low(px
));
159 return (typename
S::raw_type
)(reinterpret_cast<uintptr_t>(px
));
163 typename
S::storage_type m_s
;
166 ///////////////////////////////////////////////////////////////////////////////
171 using storage_type
= S
;
173 static ALWAYS_INLINE raw_type
get(const storage_type
& s
) {
176 static ALWAYS_INLINE
void set(storage_type
& s
, raw_type r
) {
181 template <class S
, std::memory_order read_order
, std::memory_order write_order
>
182 struct AtomicStorage
{
184 using storage_type
= std::atomic
<S
>;
186 static ALWAYS_INLINE raw_type
get(const storage_type
& s
) {
187 return s
.load(read_order
);
189 static ALWAYS_INLINE
void set(storage_type
& s
, raw_type r
) {
190 s
.store(r
, write_order
);
194 ///////////////////////////////////////////////////////////////////////////////
198 ///////////////////////////////////////////////////////////////////////////////
201 constexpr bool use_lowptr
= true;
204 using low_storage_t
= uint32_t;
207 constexpr bool use_lowptr
= false;
210 using low_storage_t
= uintptr_t;
216 detail::LowPtrImpl
<T
, detail::RawStorage
<detail::low_storage_t
>>;
219 std::memory_order read_order
= std::memory_order_relaxed
,
220 std::memory_order write_order
= std::memory_order_relaxed
>
222 detail::LowPtrImpl
<T
, detail::AtomicStorage
<detail::low_storage_t
,
226 ///////////////////////////////////////////////////////////////////////////////
230 template<class T
> class FormatValue
<HPHP::LowPtr
<T
>> {
232 explicit FormatValue(HPHP::LowPtr
<T
> v
) : m_val(v
) {}
234 template<typename Callback
>
235 void format(FormatArg
& arg
, Callback
& cb
) const {
236 FormatValue
<T
*>(m_val
.get()).format(arg
, cb
);
240 const HPHP::LowPtr
<T
> m_val
;
244 #endif // incl_HPHP_LOW_PTR_H_