LCOV - code coverage report
Current view: top level - ext - concurrence.h (source / functions) Hit Total Coverage
Test: stap.info Lines: 0 12 0.0 %
Date: 2013-03-08 Functions: 0 12 0.0 %
Branches: 0 8 0.0 %

           Branch data     Line data    Source code
       1                 :            : // Support for concurrent programing -*- C++ -*-
       2                 :            : 
       3                 :            : // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
       4                 :            : // Free Software Foundation, Inc.
       5                 :            : //
       6                 :            : // This file is part of the GNU ISO C++ Library.  This library is free
       7                 :            : // software; you can redistribute it and/or modify it under the
       8                 :            : // terms of the GNU General Public License as published by the
       9                 :            : // Free Software Foundation; either version 3, or (at your option)
      10                 :            : // any later version.
      11                 :            : 
      12                 :            : // This library is distributed in the hope that it will be useful,
      13                 :            : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            : // GNU General Public License for more details.
      16                 :            : 
      17                 :            : // Under Section 7 of GPL version 3, you are granted additional
      18                 :            : // permissions described in the GCC Runtime Library Exception, version
      19                 :            : // 3.1, as published by the Free Software Foundation.
      20                 :            : 
      21                 :            : // You should have received a copy of the GNU General Public License and
      22                 :            : // a copy of the GCC Runtime Library Exception along with this program;
      23                 :            : // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      24                 :            : // <http://www.gnu.org/licenses/>.
      25                 :            : 
      26                 :            : /** @file ext/concurrence.h
      27                 :            :  *  This file is a GNU extension to the Standard C++ Library.
      28                 :            :  */
      29                 :            : 
      30                 :            : #ifndef _CONCURRENCE_H
      31                 :            : #define _CONCURRENCE_H 1
      32                 :            : 
      33                 :            : #pragma GCC system_header
      34                 :            : 
      35                 :            : #include <exception>
      36                 :            : #include <bits/gthr.h> 
      37                 :            : #include <bits/functexcept.h>
      38                 :            : #include <bits/cpp_type_traits.h>
      39                 :            : #include <ext/type_traits.h>
      40                 :            : 
      41                 :            : namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
      42                 :            : {
      43                 :            : _GLIBCXX_BEGIN_NAMESPACE_VERSION
      44                 :            : 
      45                 :            :   // Available locking policies:
      46                 :            :   // _S_single    single-threaded code that doesn't need to be locked.
      47                 :            :   // _S_mutex     multi-threaded code that requires additional support
      48                 :            :   //              from gthr.h or abstraction layers in concurrence.h.
      49                 :            :   // _S_atomic    multi-threaded code using atomic operations.
      50                 :            :   enum _Lock_policy { _S_single, _S_mutex, _S_atomic }; 
      51                 :            : 
      52                 :            :   // Compile time constant that indicates prefered locking policy in
      53                 :            :   // the current configuration.
      54                 :            :   static const _Lock_policy __default_lock_policy = 
      55                 :            : #ifdef __GTHREADS
      56                 :            : #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
      57                 :            :      && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))
      58                 :            :   _S_atomic;
      59                 :            : #else
      60                 :            :   _S_mutex;
      61                 :            : #endif
      62                 :            : #else
      63                 :            :   _S_single;
      64                 :            : #endif
      65                 :            : 
      66                 :            :   // NB: As this is used in libsupc++, need to only depend on
      67                 :            :   // exception. No stdexception classes, no use of std::string.
      68         [ #  # ]:          0 :   class __concurrence_lock_error : public std::exception
      69                 :            :   {
      70                 :            :   public:
      71                 :            :     virtual char const*
      72                 :          0 :     what() const throw()
      73                 :          0 :     { return "__gnu_cxx::__concurrence_lock_error"; }
      74                 :            :   };
      75                 :            : 
      76         [ #  # ]:          0 :   class __concurrence_unlock_error : public std::exception
      77                 :            :   {
      78                 :            :   public:
      79                 :            :     virtual char const*
      80                 :          0 :     what() const throw()
      81                 :          0 :     { return "__gnu_cxx::__concurrence_unlock_error"; }
      82                 :            :   };
      83                 :            : 
      84         [ #  # ]:          0 :   class __concurrence_broadcast_error : public std::exception
      85                 :            :   {
      86                 :            :   public:
      87                 :            :     virtual char const*
      88                 :          0 :     what() const throw()
      89                 :          0 :     { return "__gnu_cxx::__concurrence_broadcast_error"; }
      90                 :            :   };
      91                 :            : 
      92         [ #  # ]:          0 :   class __concurrence_wait_error : public std::exception
      93                 :            :   {
      94                 :            :   public:
      95                 :            :     virtual char const*
      96                 :          0 :     what() const throw()
      97                 :          0 :     { return "__gnu_cxx::__concurrence_wait_error"; }
      98                 :            :   };
      99                 :            : 
     100                 :            :   // Substitute for concurrence_error object in the case of -fno-exceptions.
     101                 :            :   inline void
     102                 :            :   __throw_concurrence_lock_error()
     103                 :            :   {
     104                 :            : #if __EXCEPTIONS
     105                 :            :     throw __concurrence_lock_error();
     106                 :            : #else
     107                 :            :     __builtin_abort();
     108                 :            : #endif
     109                 :            :   }
     110                 :            : 
     111                 :            :   inline void
     112                 :            :   __throw_concurrence_unlock_error()
     113                 :            :   {
     114                 :            : #if __EXCEPTIONS
     115                 :            :     throw __concurrence_unlock_error();
     116                 :            : #else
     117                 :            :     __builtin_abort();
     118                 :            : #endif
     119                 :            :   }
     120                 :            : 
     121                 :            : #ifdef __GTHREAD_HAS_COND
     122                 :            :   inline void
     123                 :            :   __throw_concurrence_broadcast_error()
     124                 :            :   {
     125                 :            : #if __EXCEPTIONS
     126                 :            :     throw __concurrence_broadcast_error();
     127                 :            : #else
     128                 :            :     __builtin_abort();
     129                 :            : #endif
     130                 :            :   }
     131                 :            : 
     132                 :            :   inline void
     133                 :            :   __throw_concurrence_wait_error()
     134                 :            :   {
     135                 :            : #if __EXCEPTIONS
     136                 :            :     throw __concurrence_wait_error();
     137                 :            : #else
     138                 :            :     __builtin_abort();
     139                 :            : #endif
     140                 :            :   }
     141                 :            : #endif
     142                 :            :  
     143                 :            :   class __mutex 
     144                 :            :   {
     145                 :            :   private:
     146                 :            : #if __GTHREADS && defined __GTHREAD_MUTEX_INIT
     147                 :            :     __gthread_mutex_t _M_mutex = __GTHREAD_MUTEX_INIT;
     148                 :            : #else
     149                 :            :     __gthread_mutex_t _M_mutex;
     150                 :            : #endif
     151                 :            : 
     152                 :            :     __mutex(const __mutex&);
     153                 :            :     __mutex& operator=(const __mutex&);
     154                 :            : 
     155                 :            :   public:
     156                 :            :     __mutex() 
     157                 :            :     { 
     158                 :            : #if __GTHREADS && ! defined __GTHREAD_MUTEX_INIT
     159                 :            :       if (__gthread_active_p())
     160                 :            :         __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
     161                 :            : #endif
     162                 :            :     }
     163                 :            : 
     164                 :            : #if __GTHREADS && ! defined __GTHREAD_MUTEX_INIT
     165                 :            :     ~__mutex() 
     166                 :            :     { 
     167                 :            :       if (__gthread_active_p())
     168                 :            :         __gthread_mutex_destroy(&_M_mutex); 
     169                 :            :     }
     170                 :            : #endif 
     171                 :            : 
     172                 :            :     void lock()
     173                 :            :     {
     174                 :            : #if __GTHREADS
     175                 :            :       if (__gthread_active_p())
     176                 :            :         {
     177                 :            :           if (__gthread_mutex_lock(&_M_mutex) != 0)
     178                 :            :             __throw_concurrence_lock_error();
     179                 :            :         }
     180                 :            : #endif
     181                 :            :     }
     182                 :            :     
     183                 :            :     void unlock()
     184                 :            :     {
     185                 :            : #if __GTHREADS
     186                 :            :       if (__gthread_active_p())
     187                 :            :         {
     188                 :            :           if (__gthread_mutex_unlock(&_M_mutex) != 0)
     189                 :            :             __throw_concurrence_unlock_error();
     190                 :            :         }
     191                 :            : #endif
     192                 :            :     }
     193                 :            : 
     194                 :            :     __gthread_mutex_t* gthread_mutex(void)
     195                 :            :       { return &_M_mutex; }
     196                 :            :   };
     197                 :            : 
     198                 :            :   class __recursive_mutex 
     199                 :            :   {
     200                 :            :   private:
     201                 :            : #if __GTHREADS && defined __GTHREAD_RECURSIVE_MUTEX_INIT
     202                 :            :     __gthread_recursive_mutex_t _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
     203                 :            : #else
     204                 :            :     __gthread_recursive_mutex_t _M_mutex;
     205                 :            : #endif
     206                 :            : 
     207                 :            :     __recursive_mutex(const __recursive_mutex&);
     208                 :            :     __recursive_mutex& operator=(const __recursive_mutex&);
     209                 :            : 
     210                 :            :   public:
     211                 :            :     __recursive_mutex() 
     212                 :            :     { 
     213                 :            : #if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT
     214                 :            :       if (__gthread_active_p())
     215                 :            :         __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
     216                 :            : #endif
     217                 :            :     }
     218                 :            : 
     219                 :            : #if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT
     220                 :            :     ~__recursive_mutex()
     221                 :            :     {
     222                 :            :       if (__gthread_active_p())
     223                 :            :         _S_destroy(&_M_mutex);
     224                 :            :     }
     225                 :            : #endif
     226                 :            : 
     227                 :            :     void lock()
     228                 :            :     { 
     229                 :            : #if __GTHREADS
     230                 :            :       if (__gthread_active_p())
     231                 :            :         {
     232                 :            :           if (__gthread_recursive_mutex_lock(&_M_mutex) != 0)
     233                 :            :             __throw_concurrence_lock_error();
     234                 :            :         }
     235                 :            : #endif
     236                 :            :     }
     237                 :            :     
     238                 :            :     void unlock()
     239                 :            :     { 
     240                 :            : #if __GTHREADS
     241                 :            :       if (__gthread_active_p())
     242                 :            :         {
     243                 :            :           if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0)
     244                 :            :             __throw_concurrence_unlock_error();
     245                 :            :         }
     246                 :            : #endif
     247                 :            :     }
     248                 :            : 
     249                 :            :     __gthread_recursive_mutex_t* gthread_recursive_mutex(void)
     250                 :            :     { return &_M_mutex; }
     251                 :            : 
     252                 :            : #if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT
     253                 :            :     // FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
     254                 :            :     // so we need to obtain a __gthread_mutex_t to destroy
     255                 :            :   private:
     256                 :            :     template<typename _Mx, typename _Rm>
     257                 :            :       static void
     258                 :            :       _S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
     259                 :            :       {
     260                 :            :         __mx->counter = __rmx->counter;
     261                 :            :         __mx->sema = __rmx->sema;
     262                 :            :         __gthread_mutex_destroy(__mx);
     263                 :            :       }
     264                 :            : 
     265                 :            :     // matches a gthr-win32.h recursive mutex
     266                 :            :     template<typename _Rm>
     267                 :            :       static typename __enable_if<(bool)sizeof(&_Rm::sema), void>::__type
     268                 :            :       _S_destroy(_Rm* __mx)
     269                 :            :       {
     270                 :            :         __gthread_mutex_t __tmp;
     271                 :            :         _S_destroy_win32(&__tmp, __mx);
     272                 :            :       }
     273                 :            : 
     274                 :            :     // matches a recursive mutex with a member 'actual'
     275                 :            :     template<typename _Rm>
     276                 :            :       static typename __enable_if<(bool)sizeof(&_Rm::actual), void>::__type
     277                 :            :       _S_destroy(_Rm* __mx)
     278                 :            :       { __gthread_mutex_destroy(&__mx->actual); }
     279                 :            : 
     280                 :            :     // matches when there's only one mutex type
     281                 :            :     template<typename _Rm>
     282                 :            :       static typename
     283                 :            :       __enable_if<std::__are_same<_Rm, __gthread_mutex_t>::__value,
     284                 :            :         void>::__type
     285                 :            :       _S_destroy(_Rm* __mx)
     286                 :            :       { __gthread_mutex_destroy(__mx); }
     287                 :            : #endif
     288                 :            :   };
     289                 :            : 
     290                 :            :   /// Scoped lock idiom.
     291                 :            :   // Acquire the mutex here with a constructor call, then release with
     292                 :            :   // the destructor call in accordance with RAII style.
     293                 :            :   class __scoped_lock
     294                 :            :   {
     295                 :            :   public:
     296                 :            :     typedef __mutex __mutex_type;
     297                 :            : 
     298                 :            :   private:
     299                 :            :     __mutex_type& _M_device;
     300                 :            : 
     301                 :            :     __scoped_lock(const __scoped_lock&);
     302                 :            :     __scoped_lock& operator=(const __scoped_lock&);
     303                 :            : 
     304                 :            :   public:
     305                 :            :     explicit __scoped_lock(__mutex_type& __name) : _M_device(__name)
     306                 :            :     { _M_device.lock(); }
     307                 :            : 
     308                 :            :     ~__scoped_lock() throw()
     309                 :            :     { _M_device.unlock(); }
     310                 :            :   };
     311                 :            : 
     312                 :            : #ifdef __GTHREAD_HAS_COND
     313                 :            :   class __cond
     314                 :            :   {
     315                 :            :   private:
     316                 :            : #if __GTHREADS && defined __GTHREAD_COND_INIT
     317                 :            :     __gthread_cond_t _M_cond = __GTHREAD_COND_INIT;
     318                 :            : #else
     319                 :            :     __gthread_cond_t _M_cond;
     320                 :            : #endif
     321                 :            : 
     322                 :            :     __cond(const __cond&);
     323                 :            :     __cond& operator=(const __cond&);
     324                 :            : 
     325                 :            :   public:
     326                 :            :     __cond() 
     327                 :            :     { 
     328                 :            : #if __GTHREADS && ! defined __GTHREAD_COND_INIT
     329                 :            :       if (__gthread_active_p())
     330                 :            :         __GTHREAD_COND_INIT_FUNCTION(&_M_cond);
     331                 :            : #endif
     332                 :            :     }
     333                 :            : 
     334                 :            : #if __GTHREADS && ! defined __GTHREAD_COND_INIT
     335                 :            :     ~__cond() 
     336                 :            :     { 
     337                 :            :       if (__gthread_active_p())
     338                 :            :         __gthread_cond_destroy(&_M_cond); 
     339                 :            :     }
     340                 :            : #endif 
     341                 :            : 
     342                 :            :     void broadcast()
     343                 :            :     {
     344                 :            : #if __GTHREADS
     345                 :            :       if (__gthread_active_p())
     346                 :            :         {
     347                 :            :           if (__gthread_cond_broadcast(&_M_cond) != 0)
     348                 :            :             __throw_concurrence_broadcast_error();
     349                 :            :         }
     350                 :            : #endif
     351                 :            :     }
     352                 :            : 
     353                 :            :     void wait(__mutex *mutex)
     354                 :            :     {
     355                 :            : #if __GTHREADS
     356                 :            :       {
     357                 :            :           if (__gthread_cond_wait(&_M_cond, mutex->gthread_mutex()) != 0)
     358                 :            :             __throw_concurrence_wait_error();
     359                 :            :       }
     360                 :            : #endif
     361                 :            :     }
     362                 :            : 
     363                 :            :     void wait_recursive(__recursive_mutex *mutex)
     364                 :            :     {
     365                 :            : #if __GTHREADS
     366                 :            :       {
     367                 :            :           if (__gthread_cond_wait_recursive(&_M_cond,
     368                 :            :                                             mutex->gthread_recursive_mutex())
     369                 :            :               != 0)
     370                 :            :             __throw_concurrence_wait_error();
     371                 :            :       }
     372                 :            : #endif
     373                 :            :     }
     374                 :            :   };
     375                 :            : #endif
     376                 :            : 
     377                 :            : _GLIBCXX_END_NAMESPACE_VERSION
     378                 :            : } // namespace
     379                 :            : 
     380                 :            : #endif

Generated by: LCOV version 1.9