Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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