xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/shared_ptr_atomic.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj // shared_ptr atomic access -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 2014-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj 
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj 
25*38fd1498Szrj /** @file bits/shared_ptr_atomic.h
26*38fd1498Szrj  *  This is an internal header file, included by other library headers.
27*38fd1498Szrj  *  Do not attempt to use it directly. @headername{memory}
28*38fd1498Szrj  */
29*38fd1498Szrj 
30*38fd1498Szrj #ifndef _SHARED_PTR_ATOMIC_H
31*38fd1498Szrj #define _SHARED_PTR_ATOMIC_H 1
32*38fd1498Szrj 
33*38fd1498Szrj #include <bits/atomic_base.h>
34*38fd1498Szrj 
_GLIBCXX_VISIBILITY(default)35*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
36*38fd1498Szrj {
37*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
38*38fd1498Szrj 
39*38fd1498Szrj   /**
40*38fd1498Szrj    * @addtogroup pointer_abstractions
41*38fd1498Szrj    * @{
42*38fd1498Szrj    */
43*38fd1498Szrj 
44*38fd1498Szrj   struct _Sp_locker
45*38fd1498Szrj   {
46*38fd1498Szrj     _Sp_locker(const _Sp_locker&) = delete;
47*38fd1498Szrj     _Sp_locker& operator=(const _Sp_locker&) = delete;
48*38fd1498Szrj 
49*38fd1498Szrj #ifdef __GTHREADS
50*38fd1498Szrj     explicit
51*38fd1498Szrj     _Sp_locker(const void*) noexcept;
52*38fd1498Szrj     _Sp_locker(const void*, const void*) noexcept;
53*38fd1498Szrj     ~_Sp_locker();
54*38fd1498Szrj 
55*38fd1498Szrj   private:
56*38fd1498Szrj     unsigned char _M_key1;
57*38fd1498Szrj     unsigned char _M_key2;
58*38fd1498Szrj #else
59*38fd1498Szrj     explicit _Sp_locker(const void*, const void* = nullptr) { }
60*38fd1498Szrj #endif
61*38fd1498Szrj   };
62*38fd1498Szrj 
63*38fd1498Szrj   /**
64*38fd1498Szrj    *  @brief  Report whether shared_ptr atomic operations are lock-free.
65*38fd1498Szrj    *  @param  __p A non-null pointer to a shared_ptr object.
66*38fd1498Szrj    *  @return True if atomic access to @c *__p is lock-free, false otherwise.
67*38fd1498Szrj    *  @{
68*38fd1498Szrj   */
69*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
70*38fd1498Szrj     inline bool
71*38fd1498Szrj     atomic_is_lock_free(const __shared_ptr<_Tp, _Lp>* __p)
72*38fd1498Szrj     {
73*38fd1498Szrj #ifdef __GTHREADS
74*38fd1498Szrj       return __gthread_active_p() == 0;
75*38fd1498Szrj #else
76*38fd1498Szrj       return true;
77*38fd1498Szrj #endif
78*38fd1498Szrj     }
79*38fd1498Szrj 
80*38fd1498Szrj   template<typename _Tp>
81*38fd1498Szrj     inline bool
82*38fd1498Szrj     atomic_is_lock_free(const shared_ptr<_Tp>* __p)
83*38fd1498Szrj     { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
84*38fd1498Szrj 
85*38fd1498Szrj   // @}
86*38fd1498Szrj 
87*38fd1498Szrj   /**
88*38fd1498Szrj    *  @brief  Atomic load for shared_ptr objects.
89*38fd1498Szrj    *  @param  __p A non-null pointer to a shared_ptr object.
90*38fd1498Szrj    *  @return @c *__p
91*38fd1498Szrj    *
92*38fd1498Szrj    *  The memory order shall not be @c memory_order_release or
93*38fd1498Szrj    *  @c memory_order_acq_rel.
94*38fd1498Szrj    *  @{
95*38fd1498Szrj   */
96*38fd1498Szrj   template<typename _Tp>
97*38fd1498Szrj     inline shared_ptr<_Tp>
98*38fd1498Szrj     atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order)
99*38fd1498Szrj     {
100*38fd1498Szrj       _Sp_locker __lock{__p};
101*38fd1498Szrj       return *__p;
102*38fd1498Szrj     }
103*38fd1498Szrj 
104*38fd1498Szrj   template<typename _Tp>
105*38fd1498Szrj     inline shared_ptr<_Tp>
106*38fd1498Szrj     atomic_load(const shared_ptr<_Tp>* __p)
107*38fd1498Szrj     { return std::atomic_load_explicit(__p, memory_order_seq_cst); }
108*38fd1498Szrj 
109*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
110*38fd1498Szrj     inline __shared_ptr<_Tp, _Lp>
111*38fd1498Szrj     atomic_load_explicit(const __shared_ptr<_Tp, _Lp>* __p, memory_order)
112*38fd1498Szrj     {
113*38fd1498Szrj       _Sp_locker __lock{__p};
114*38fd1498Szrj       return *__p;
115*38fd1498Szrj     }
116*38fd1498Szrj 
117*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
118*38fd1498Szrj     inline __shared_ptr<_Tp, _Lp>
119*38fd1498Szrj     atomic_load(const __shared_ptr<_Tp, _Lp>* __p)
120*38fd1498Szrj     { return std::atomic_load_explicit(__p, memory_order_seq_cst); }
121*38fd1498Szrj   // @}
122*38fd1498Szrj 
123*38fd1498Szrj   /**
124*38fd1498Szrj    *  @brief  Atomic store for shared_ptr objects.
125*38fd1498Szrj    *  @param  __p A non-null pointer to a shared_ptr object.
126*38fd1498Szrj    *  @param  __r The value to store.
127*38fd1498Szrj    *
128*38fd1498Szrj    *  The memory order shall not be @c memory_order_acquire or
129*38fd1498Szrj    *  @c memory_order_acq_rel.
130*38fd1498Szrj    *  @{
131*38fd1498Szrj   */
132*38fd1498Szrj   template<typename _Tp>
133*38fd1498Szrj     inline void
134*38fd1498Szrj     atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r,
135*38fd1498Szrj 			  memory_order)
136*38fd1498Szrj     {
137*38fd1498Szrj       _Sp_locker __lock{__p};
138*38fd1498Szrj       __p->swap(__r); // use swap so that **__p not destroyed while lock held
139*38fd1498Szrj     }
140*38fd1498Szrj 
141*38fd1498Szrj   template<typename _Tp>
142*38fd1498Szrj     inline void
143*38fd1498Szrj     atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
144*38fd1498Szrj     { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); }
145*38fd1498Szrj 
146*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
147*38fd1498Szrj     inline void
148*38fd1498Szrj     atomic_store_explicit(__shared_ptr<_Tp, _Lp>* __p,
149*38fd1498Szrj 			  __shared_ptr<_Tp, _Lp> __r,
150*38fd1498Szrj 			  memory_order)
151*38fd1498Szrj     {
152*38fd1498Szrj       _Sp_locker __lock{__p};
153*38fd1498Szrj       __p->swap(__r); // use swap so that **__p not destroyed while lock held
154*38fd1498Szrj     }
155*38fd1498Szrj 
156*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
157*38fd1498Szrj     inline void
158*38fd1498Szrj     atomic_store(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r)
159*38fd1498Szrj     { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); }
160*38fd1498Szrj   // @}
161*38fd1498Szrj 
162*38fd1498Szrj   /**
163*38fd1498Szrj    *  @brief  Atomic exchange for shared_ptr objects.
164*38fd1498Szrj    *  @param  __p A non-null pointer to a shared_ptr object.
165*38fd1498Szrj    *  @param  __r New value to store in @c *__p.
166*38fd1498Szrj    *  @return The original value of @c *__p
167*38fd1498Szrj    *  @{
168*38fd1498Szrj   */
169*38fd1498Szrj   template<typename _Tp>
170*38fd1498Szrj     inline shared_ptr<_Tp>
171*38fd1498Szrj     atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r,
172*38fd1498Szrj 			     memory_order)
173*38fd1498Szrj     {
174*38fd1498Szrj       _Sp_locker __lock{__p};
175*38fd1498Szrj       __p->swap(__r);
176*38fd1498Szrj       return __r;
177*38fd1498Szrj     }
178*38fd1498Szrj 
179*38fd1498Szrj   template<typename _Tp>
180*38fd1498Szrj     inline shared_ptr<_Tp>
181*38fd1498Szrj     atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
182*38fd1498Szrj     {
183*38fd1498Szrj       return std::atomic_exchange_explicit(__p, std::move(__r),
184*38fd1498Szrj 					   memory_order_seq_cst);
185*38fd1498Szrj     }
186*38fd1498Szrj 
187*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
188*38fd1498Szrj     inline __shared_ptr<_Tp, _Lp>
189*38fd1498Szrj     atomic_exchange_explicit(__shared_ptr<_Tp, _Lp>* __p,
190*38fd1498Szrj 			     __shared_ptr<_Tp, _Lp> __r,
191*38fd1498Szrj 			     memory_order)
192*38fd1498Szrj     {
193*38fd1498Szrj       _Sp_locker __lock{__p};
194*38fd1498Szrj       __p->swap(__r);
195*38fd1498Szrj       return __r;
196*38fd1498Szrj     }
197*38fd1498Szrj 
198*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
199*38fd1498Szrj     inline __shared_ptr<_Tp, _Lp>
200*38fd1498Szrj     atomic_exchange(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r)
201*38fd1498Szrj     {
202*38fd1498Szrj       return std::atomic_exchange_explicit(__p, std::move(__r),
203*38fd1498Szrj 					   memory_order_seq_cst);
204*38fd1498Szrj     }
205*38fd1498Szrj   // @}
206*38fd1498Szrj 
207*38fd1498Szrj   /**
208*38fd1498Szrj    *  @brief  Atomic compare-and-swap for shared_ptr objects.
209*38fd1498Szrj    *  @param  __p A non-null pointer to a shared_ptr object.
210*38fd1498Szrj    *  @param  __v A non-null pointer to a shared_ptr object.
211*38fd1498Szrj    *  @param  __w A non-null pointer to a shared_ptr object.
212*38fd1498Szrj    *  @return True if @c *__p was equivalent to @c *__v, false otherwise.
213*38fd1498Szrj    *
214*38fd1498Szrj    *  The memory order for failure shall not be @c memory_order_release or
215*38fd1498Szrj    *  @c memory_order_acq_rel, or stronger than the memory order for success.
216*38fd1498Szrj    *  @{
217*38fd1498Szrj   */
218*38fd1498Szrj   template<typename _Tp>
219*38fd1498Szrj     bool
220*38fd1498Szrj     atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
221*38fd1498Szrj 					    shared_ptr<_Tp>* __v,
222*38fd1498Szrj 					    shared_ptr<_Tp> __w,
223*38fd1498Szrj 					    memory_order,
224*38fd1498Szrj 					    memory_order)
225*38fd1498Szrj     {
226*38fd1498Szrj       shared_ptr<_Tp> __x; // goes out of scope after __lock
227*38fd1498Szrj       _Sp_locker __lock{__p, __v};
228*38fd1498Szrj       owner_less<shared_ptr<_Tp>> __less;
229*38fd1498Szrj       if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p))
230*38fd1498Szrj 	{
231*38fd1498Szrj 	  __x = std::move(*__p);
232*38fd1498Szrj 	  *__p = std::move(__w);
233*38fd1498Szrj 	  return true;
234*38fd1498Szrj 	}
235*38fd1498Szrj       __x = std::move(*__v);
236*38fd1498Szrj       *__v = *__p;
237*38fd1498Szrj       return false;
238*38fd1498Szrj     }
239*38fd1498Szrj 
240*38fd1498Szrj   template<typename _Tp>
241*38fd1498Szrj     inline bool
242*38fd1498Szrj     atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
243*38fd1498Szrj 				 shared_ptr<_Tp> __w)
244*38fd1498Szrj     {
245*38fd1498Szrj       return std::atomic_compare_exchange_strong_explicit(__p, __v,
246*38fd1498Szrj 	  std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
247*38fd1498Szrj     }
248*38fd1498Szrj 
249*38fd1498Szrj   template<typename _Tp>
250*38fd1498Szrj     inline bool
251*38fd1498Szrj     atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
252*38fd1498Szrj 					  shared_ptr<_Tp>* __v,
253*38fd1498Szrj 					  shared_ptr<_Tp> __w,
254*38fd1498Szrj 					  memory_order __success,
255*38fd1498Szrj 					  memory_order __failure)
256*38fd1498Szrj     {
257*38fd1498Szrj       return std::atomic_compare_exchange_strong_explicit(__p, __v,
258*38fd1498Szrj 	  std::move(__w), __success, __failure);
259*38fd1498Szrj     }
260*38fd1498Szrj 
261*38fd1498Szrj   template<typename _Tp>
262*38fd1498Szrj     inline bool
263*38fd1498Szrj     atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
264*38fd1498Szrj 				 shared_ptr<_Tp> __w)
265*38fd1498Szrj     {
266*38fd1498Szrj       return std::atomic_compare_exchange_weak_explicit(__p, __v,
267*38fd1498Szrj 	  std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
268*38fd1498Szrj     }
269*38fd1498Szrj 
270*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
271*38fd1498Szrj     bool
272*38fd1498Szrj     atomic_compare_exchange_strong_explicit(__shared_ptr<_Tp, _Lp>* __p,
273*38fd1498Szrj 					    __shared_ptr<_Tp, _Lp>* __v,
274*38fd1498Szrj 					    __shared_ptr<_Tp, _Lp> __w,
275*38fd1498Szrj 					    memory_order,
276*38fd1498Szrj 					    memory_order)
277*38fd1498Szrj     {
278*38fd1498Szrj       __shared_ptr<_Tp, _Lp> __x; // goes out of scope after __lock
279*38fd1498Szrj       _Sp_locker __lock{__p, __v};
280*38fd1498Szrj       owner_less<__shared_ptr<_Tp, _Lp>> __less;
281*38fd1498Szrj       if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p))
282*38fd1498Szrj 	{
283*38fd1498Szrj 	  __x = std::move(*__p);
284*38fd1498Szrj 	  *__p = std::move(__w);
285*38fd1498Szrj 	  return true;
286*38fd1498Szrj 	}
287*38fd1498Szrj       __x = std::move(*__v);
288*38fd1498Szrj       *__v = *__p;
289*38fd1498Szrj       return false;
290*38fd1498Szrj     }
291*38fd1498Szrj 
292*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
293*38fd1498Szrj     inline bool
294*38fd1498Szrj     atomic_compare_exchange_strong(__shared_ptr<_Tp, _Lp>* __p,
295*38fd1498Szrj 				   __shared_ptr<_Tp, _Lp>* __v,
296*38fd1498Szrj 				   __shared_ptr<_Tp, _Lp> __w)
297*38fd1498Szrj     {
298*38fd1498Szrj       return std::atomic_compare_exchange_strong_explicit(__p, __v,
299*38fd1498Szrj 	  std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
300*38fd1498Szrj     }
301*38fd1498Szrj 
302*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
303*38fd1498Szrj     inline bool
304*38fd1498Szrj     atomic_compare_exchange_weak_explicit(__shared_ptr<_Tp, _Lp>* __p,
305*38fd1498Szrj 					  __shared_ptr<_Tp, _Lp>* __v,
306*38fd1498Szrj 					  __shared_ptr<_Tp, _Lp> __w,
307*38fd1498Szrj 					  memory_order __success,
308*38fd1498Szrj 					  memory_order __failure)
309*38fd1498Szrj     {
310*38fd1498Szrj       return std::atomic_compare_exchange_strong_explicit(__p, __v,
311*38fd1498Szrj 	  std::move(__w), __success, __failure);
312*38fd1498Szrj     }
313*38fd1498Szrj 
314*38fd1498Szrj   template<typename _Tp, _Lock_policy _Lp>
315*38fd1498Szrj     inline bool
316*38fd1498Szrj     atomic_compare_exchange_weak(__shared_ptr<_Tp, _Lp>* __p,
317*38fd1498Szrj 				 __shared_ptr<_Tp, _Lp>* __v,
318*38fd1498Szrj 				 __shared_ptr<_Tp, _Lp> __w)
319*38fd1498Szrj     {
320*38fd1498Szrj       return std::atomic_compare_exchange_weak_explicit(__p, __v,
321*38fd1498Szrj 	  std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
322*38fd1498Szrj     }
323*38fd1498Szrj   // @}
324*38fd1498Szrj 
325*38fd1498Szrj   // @} group pointer_abstractions
326*38fd1498Szrj 
327*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
328*38fd1498Szrj } // namespace
329*38fd1498Szrj 
330*38fd1498Szrj #endif // _SHARED_PTR_ATOMIC_H
331