libstdc++
|
00001 // shared_ptr atomic access -*- C++ -*- 00002 00003 // Copyright (C) 2014-2015 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file bits/shared_ptr_atomic.h 00026 * This is an internal header file, included by other library headers. 00027 * Do not attempt to use it directly. @headername{memory} 00028 */ 00029 00030 #ifndef _SHARED_PTR_ATOMIC_H 00031 #define _SHARED_PTR_ATOMIC_H 1 00032 00033 #include <bits/atomic_base.h> 00034 00035 namespace std _GLIBCXX_VISIBILITY(default) 00036 { 00037 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00038 00039 /** 00040 * @addtogroup pointer_abstractions 00041 * @{ 00042 */ 00043 00044 struct _Sp_locker 00045 { 00046 _Sp_locker(const _Sp_locker&) = delete; 00047 _Sp_locker& operator=(const _Sp_locker&) = delete; 00048 00049 #ifdef __GTHREADS 00050 explicit 00051 _Sp_locker(const void*) noexcept; 00052 _Sp_locker(const void*, const void*) noexcept; 00053 ~_Sp_locker(); 00054 00055 private: 00056 unsigned char _M_key1; 00057 unsigned char _M_key2; 00058 #else 00059 explicit _Sp_locker(const void*, const void* = nullptr) { } 00060 #endif 00061 }; 00062 00063 /** 00064 * @brief Report whether shared_ptr atomic operations are lock-free. 00065 * @param __p A non-null pointer to a shared_ptr object. 00066 * @return True if atomic access to @c *__p is lock-free, false otherwise. 00067 * @{ 00068 */ 00069 template<typename _Tp, _Lock_policy _Lp> 00070 inline bool 00071 atomic_is_lock_free(const __shared_ptr<_Tp, _Lp>* __p) 00072 { 00073 #ifdef __GTHREADS 00074 return __gthread_active_p() == 0; 00075 #else 00076 return true; 00077 #endif 00078 } 00079 00080 template<typename _Tp> 00081 inline bool 00082 atomic_is_lock_free(const shared_ptr<_Tp>* __p) 00083 { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); } 00084 00085 // @} 00086 00087 /** 00088 * @brief Atomic load for shared_ptr objects. 00089 * @param __p A non-null pointer to a shared_ptr object. 00090 * @return @c *__p 00091 * 00092 * The memory order shall not be @c memory_order_release or 00093 * @c memory_order_acq_rel. 00094 * @{ 00095 */ 00096 template<typename _Tp> 00097 inline shared_ptr<_Tp> 00098 atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order) 00099 { 00100 _Sp_locker __lock{__p}; 00101 return *__p; 00102 } 00103 00104 template<typename _Tp> 00105 inline shared_ptr<_Tp> 00106 atomic_load(const shared_ptr<_Tp>* __p) 00107 { return std::atomic_load_explicit(__p, memory_order_seq_cst); } 00108 00109 template<typename _Tp, _Lock_policy _Lp> 00110 inline __shared_ptr<_Tp, _Lp> 00111 atomic_load_explicit(const __shared_ptr<_Tp, _Lp>* __p, memory_order) 00112 { 00113 _Sp_locker __lock{__p}; 00114 return *__p; 00115 } 00116 00117 template<typename _Tp, _Lock_policy _Lp> 00118 inline __shared_ptr<_Tp, _Lp> 00119 atomic_load(const __shared_ptr<_Tp, _Lp>* __p) 00120 { return std::atomic_load_explicit(__p, memory_order_seq_cst); } 00121 // @} 00122 00123 /** 00124 * @brief Atomic store for shared_ptr objects. 00125 * @param __p A non-null pointer to a shared_ptr object. 00126 * @param __r The value to store. 00127 * 00128 * The memory order shall not be @c memory_order_acquire or 00129 * @c memory_order_acq_rel. 00130 * @{ 00131 */ 00132 template<typename _Tp> 00133 inline void 00134 atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, 00135 memory_order) 00136 { 00137 _Sp_locker __lock{__p}; 00138 __p->swap(__r); // use swap so that **__p not destroyed while lock held 00139 } 00140 00141 template<typename _Tp> 00142 inline void 00143 atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) 00144 { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); } 00145 00146 template<typename _Tp, _Lock_policy _Lp> 00147 inline void 00148 atomic_store_explicit(__shared_ptr<_Tp, _Lp>* __p, 00149 __shared_ptr<_Tp, _Lp> __r, 00150 memory_order) 00151 { 00152 _Sp_locker __lock{__p}; 00153 __p->swap(__r); // use swap so that **__p not destroyed while lock held 00154 } 00155 00156 template<typename _Tp, _Lock_policy _Lp> 00157 inline void 00158 atomic_store(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r) 00159 { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); } 00160 // @} 00161 00162 /** 00163 * @brief Atomic exchange for shared_ptr objects. 00164 * @param __p A non-null pointer to a shared_ptr object. 00165 * @param __r New value to store in @c *__p. 00166 * @return The original value of @c *__p 00167 * @{ 00168 */ 00169 template<typename _Tp> 00170 inline shared_ptr<_Tp> 00171 atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, 00172 memory_order) 00173 { 00174 _Sp_locker __lock{__p}; 00175 __p->swap(__r); 00176 return __r; 00177 } 00178 00179 template<typename _Tp> 00180 inline shared_ptr<_Tp> 00181 atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) 00182 { 00183 return std::atomic_exchange_explicit(__p, std::move(__r), 00184 memory_order_seq_cst); 00185 } 00186 00187 template<typename _Tp, _Lock_policy _Lp> 00188 inline __shared_ptr<_Tp, _Lp> 00189 atomic_exchange_explicit(__shared_ptr<_Tp, _Lp>* __p, 00190 __shared_ptr<_Tp, _Lp> __r, 00191 memory_order) 00192 { 00193 _Sp_locker __lock{__p}; 00194 __p->swap(__r); 00195 return __r; 00196 } 00197 00198 template<typename _Tp, _Lock_policy _Lp> 00199 inline __shared_ptr<_Tp, _Lp> 00200 atomic_exchange(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r) 00201 { 00202 return std::atomic_exchange_explicit(__p, std::move(__r), 00203 memory_order_seq_cst); 00204 } 00205 // @} 00206 00207 /** 00208 * @brief Atomic compare-and-swap for shared_ptr objects. 00209 * @param __p A non-null pointer to a shared_ptr object. 00210 * @param __v A non-null pointer to a shared_ptr object. 00211 * @param __w A non-null pointer to a shared_ptr object. 00212 * @return True if @c *__p was equivalent to @c *__v, false otherwise. 00213 * 00214 * The memory order for failure shall not be @c memory_order_release or 00215 * @c memory_order_acq_rel, or stronger than the memory order for success. 00216 * @{ 00217 */ 00218 template<typename _Tp> 00219 bool 00220 atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, 00221 shared_ptr<_Tp>* __v, 00222 shared_ptr<_Tp> __w, 00223 memory_order, 00224 memory_order) 00225 { 00226 shared_ptr<_Tp> __x; // goes out of scope after __lock 00227 _Sp_locker __lock{__p, __v}; 00228 owner_less<shared_ptr<_Tp>> __less; 00229 if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p)) 00230 { 00231 __x = std::move(*__p); 00232 *__p = std::move(__w); 00233 return true; 00234 } 00235 __x = std::move(*__v); 00236 *__v = *__p; 00237 return false; 00238 } 00239 00240 template<typename _Tp> 00241 inline bool 00242 atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, 00243 shared_ptr<_Tp> __w) 00244 { 00245 return std::atomic_compare_exchange_strong_explicit(__p, __v, 00246 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 00247 } 00248 00249 template<typename _Tp> 00250 inline bool 00251 atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, 00252 shared_ptr<_Tp>* __v, 00253 shared_ptr<_Tp> __w, 00254 memory_order __success, 00255 memory_order __failure) 00256 { 00257 return std::atomic_compare_exchange_strong_explicit(__p, __v, 00258 std::move(__w), __success, __failure); 00259 } 00260 00261 template<typename _Tp> 00262 inline bool 00263 atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, 00264 shared_ptr<_Tp> __w) 00265 { 00266 return std::atomic_compare_exchange_weak_explicit(__p, __v, 00267 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 00268 } 00269 00270 template<typename _Tp, _Lock_policy _Lp> 00271 bool 00272 atomic_compare_exchange_strong_explicit(__shared_ptr<_Tp, _Lp>* __p, 00273 __shared_ptr<_Tp, _Lp>* __v, 00274 __shared_ptr<_Tp, _Lp> __w, 00275 memory_order, 00276 memory_order) 00277 { 00278 __shared_ptr<_Tp, _Lp> __x; // goes out of scope after __lock 00279 _Sp_locker __lock{__p, __v}; 00280 owner_less<__shared_ptr<_Tp, _Lp>> __less; 00281 if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p)) 00282 { 00283 __x = std::move(*__p); 00284 *__p = std::move(__w); 00285 return true; 00286 } 00287 __x = std::move(*__v); 00288 *__v = *__p; 00289 return false; 00290 } 00291 00292 template<typename _Tp, _Lock_policy _Lp> 00293 inline bool 00294 atomic_compare_exchange_strong(__shared_ptr<_Tp, _Lp>* __p, 00295 __shared_ptr<_Tp, _Lp>* __v, 00296 __shared_ptr<_Tp, _Lp> __w) 00297 { 00298 return std::atomic_compare_exchange_strong_explicit(__p, __v, 00299 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 00300 } 00301 00302 template<typename _Tp, _Lock_policy _Lp> 00303 inline bool 00304 atomic_compare_exchange_weak_explicit(__shared_ptr<_Tp, _Lp>* __p, 00305 __shared_ptr<_Tp, _Lp>* __v, 00306 __shared_ptr<_Tp, _Lp> __w, 00307 memory_order __success, 00308 memory_order __failure) 00309 { 00310 return std::atomic_compare_exchange_strong_explicit(__p, __v, 00311 std::move(__w), __success, __failure); 00312 } 00313 00314 template<typename _Tp, _Lock_policy _Lp> 00315 inline bool 00316 atomic_compare_exchange_weak(__shared_ptr<_Tp, _Lp>* __p, 00317 __shared_ptr<_Tp, _Lp>* __v, 00318 __shared_ptr<_Tp, _Lp> __w) 00319 { 00320 return std::atomic_compare_exchange_weak_explicit(__p, __v, 00321 std::move(__w), memory_order_seq_cst, memory_order_seq_cst); 00322 } 00323 // @} 00324 00325 // @} group pointer_abstractions 00326 00327 _GLIBCXX_END_NAMESPACE_VERSION 00328 } // namespace 00329 00330 #endif // _SHARED_PTR_ATOMIC_H