LCOV - code coverage report
Current view: top level - usr/include/c++/4.4/tr1_impl - boost_sp_counted_base.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 8 15 53.3 %
Date: 2017-07-14 10:03:36 Functions: 4 8 50.0 %

          Line data    Source code
       1             : // <tr1_impl/boost_sp_counted_base.h> -*- C++ -*-
       2             : 
       3             : // Copyright (C) 2007, 2009 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             : //  shared_count.hpp
      26             : //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
      27             : 
      28             : //  shared_ptr.hpp
      29             : //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
      30             : //  Copyright (C) 2001, 2002, 2003 Peter Dimov
      31             : 
      32             : //  weak_ptr.hpp
      33             : //  Copyright (C) 2001, 2002, 2003 Peter Dimov
      34             : 
      35             : //  enable_shared_from_this.hpp
      36             : //  Copyright (C) 2002 Peter Dimov
      37             : 
      38             : // Distributed under the Boost Software License, Version 1.0. (See
      39             : // accompanying file LICENSE_1_0.txt or copy at
      40             : // http://www.boost.org/LICENSE_1_0.txt)
      41             : 
      42             : // GCC Note:  based on version 1.32.0 of the Boost library.
      43             : 
      44             : /** @file tr1_impl/boost_sp_counted_base.h
      45             :  *  This is an internal header file, included by other library headers.
      46             :  *  You should not attempt to use it directly.
      47             :  */
      48             : 
      49             : 
      50             : namespace std
      51             : {
      52             : _GLIBCXX_BEGIN_NAMESPACE_TR1
      53             : 
      54             :   class bad_weak_ptr : public std::exception
      55             :   {
      56             :   public:
      57             :     virtual char const*
      58             :     what() const throw()
      59             : #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
      60             :     { return "std::bad_weak_ptr"; }
      61             : #else
      62             :     { return "tr1::bad_weak_ptr"; }
      63             : #endif
      64             :   };
      65             : 
      66             :   // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
      67             :   inline void
      68             :   __throw_bad_weak_ptr()
      69             :   {
      70             : #if __EXCEPTIONS
      71             :     throw bad_weak_ptr();
      72             : #else
      73             :     __builtin_abort();
      74             : #endif
      75             :   }
      76             : 
      77             :   using __gnu_cxx::_Lock_policy;
      78             :   using __gnu_cxx::__default_lock_policy;
      79             :   using __gnu_cxx::_S_single;
      80             :   using __gnu_cxx::_S_mutex;
      81             :   using __gnu_cxx::_S_atomic;
      82             : 
      83             :   // Empty helper class except when the template argument is _S_mutex.
      84             :   template<_Lock_policy _Lp>
      85             :     class _Mutex_base
      86      142524 :     {
      87             :     protected:
      88             :       // The atomic policy uses fully-fenced builtins, single doesn't care.
      89             :       enum { _S_need_barriers = 0 };
      90             :     };
      91             : 
      92             :   template<>
      93             :     class _Mutex_base<_S_mutex>
      94             :     : public __gnu_cxx::__mutex
      95             :     {
      96             :     protected:
      97             :       // This policy is used when atomic builtins are not available.
      98             :       // The replacement atomic operations might not have the necessary
      99             :       // memory barriers.
     100             :       enum { _S_need_barriers = 1 };
     101             :     };
     102             : 
     103             :   template<_Lock_policy _Lp = __default_lock_policy>
     104             :     class _Sp_counted_base
     105             :     : public _Mutex_base<_Lp>
     106             :     {
     107             :     public:  
     108      142524 :       _Sp_counted_base()
     109      142524 :       : _M_use_count(1), _M_weak_count(1) { }
     110             :       
     111             :       virtual
     112           0 :       ~_Sp_counted_base() // nothrow 
     113           0 :       { }
     114             :   
     115             :       // Called when _M_use_count drops to zero, to release the resources
     116             :       // managed by *this.
     117             :       virtual void
     118             :       _M_dispose() = 0; // nothrow
     119             :       
     120             :       // Called when _M_weak_count drops to zero.
     121             :       virtual void
     122           0 :       _M_destroy() // nothrow
     123           0 :       { delete this; }
     124             :       
     125             :       virtual void*
     126             :       _M_get_deleter(const std::type_info&) = 0;
     127             : 
     128             :       void
     129      142524 :       _M_add_ref_copy()
     130      142524 :       { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
     131             :   
     132             :       void
     133             :       _M_add_ref_lock();
     134             :       
     135             :       void
     136      142524 :       _M_release() // nothrow
     137             :       {
     138      142524 :         if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
     139             :           {
     140           0 :             _M_dispose();
     141             :             // There must be a memory barrier between dispose() and destroy()
     142             :             // to ensure that the effects of dispose() are observed in the
     143             :             // thread that runs destroy().
     144             :             // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
     145             :             if (_Mutex_base<_Lp>::_S_need_barriers)
     146             :               {
     147             :                 _GLIBCXX_READ_MEM_BARRIER;
     148             :                 _GLIBCXX_WRITE_MEM_BARRIER;
     149             :               }
     150             : 
     151           0 :             if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
     152             :                                                        -1) == 1)
     153           0 :               _M_destroy();
     154             :           }
     155      142524 :       }
     156             :   
     157             :       void
     158             :       _M_weak_add_ref() // nothrow
     159             :       { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
     160             : 
     161             :       void
     162             :       _M_weak_release() // nothrow
     163             :       {
     164             :         if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
     165             :           {
     166             :             if (_Mutex_base<_Lp>::_S_need_barriers)
     167             :               {
     168             :                 // See _M_release(),
     169             :                 // destroy() must observe results of dispose()
     170             :                 _GLIBCXX_READ_MEM_BARRIER;
     171             :                 _GLIBCXX_WRITE_MEM_BARRIER;
     172             :               }
     173             :             _M_destroy();
     174             :           }
     175             :       }
     176             :   
     177             :       long
     178             :       _M_get_use_count() const // nothrow
     179             :       {
     180             :         // No memory barrier is used here so there is no synchronization
     181             :         // with other threads.
     182             :         return const_cast<const volatile _Atomic_word&>(_M_use_count);
     183             :       }
     184             : 
     185             :     private:  
     186             :       _Sp_counted_base(_Sp_counted_base const&);
     187             :       _Sp_counted_base& operator=(_Sp_counted_base const&);
     188             : 
     189             :       _Atomic_word  _M_use_count;     // #shared
     190             :       _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
     191             :     };
     192             : 
     193             :   template<>
     194             :     inline void
     195             :     _Sp_counted_base<_S_single>::
     196             :     _M_add_ref_lock()
     197             :     {
     198             :       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
     199             :         {
     200             :           _M_use_count = 0;
     201             :           __throw_bad_weak_ptr();
     202             :         }
     203             :     }
     204             : 
     205             :   template<>
     206             :     inline void
     207             :     _Sp_counted_base<_S_mutex>::
     208             :     _M_add_ref_lock()
     209             :     {
     210             :       __gnu_cxx::__scoped_lock sentry(*this);
     211             :       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
     212             :         {
     213             :           _M_use_count = 0;
     214             :           __throw_bad_weak_ptr();
     215             :         }
     216             :     }
     217             : 
     218             :   template<> 
     219             :     inline void
     220             :     _Sp_counted_base<_S_atomic>::
     221             :     _M_add_ref_lock()
     222             :     {
     223             :       // Perform lock-free add-if-not-zero operation.
     224             :       _Atomic_word __count;
     225             :       do
     226             :         {
     227             :           __count = _M_use_count;
     228             :           if (__count == 0)
     229             :             __throw_bad_weak_ptr();
     230             :           
     231             :           // Replace the current counter value with the old value + 1, as
     232             :           // long as it's not changed meanwhile. 
     233             :         }
     234             :       while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
     235             :                                            __count + 1));
     236             :     }
     237             : 
     238             : _GLIBCXX_END_NAMESPACE_TR1
     239             : }

Generated by: LCOV version 1.11