libstdc++
shared_ptr_atomic.h
Go to the documentation of this file.
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