# concurrence.h

Go to the documentation of this file.

    00001 // Support for concurrent programing -*- C++ -*-
    00002
    00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009
    00004 // Free Software Foundation, Inc.
    00005 //
    00006 // This file is part of the GNU ISO C++ Library.  This library is free
    00007 // software; you can redistribute it and/or modify it under the
    00008 // terms of the GNU General Public License as published by the
    00009 // Free Software Foundation; either version 3, or (at your option)
    00010 // any later version.
    00011
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 // GNU General Public License for more details.
    00016
    00017 // Under Section 7 of GPL version 3, you are granted additional
    00018 // permissions described in the GCC Runtime Library Exception, version
    00019 // 3.1, as published by the Free Software Foundation.
    00020
    00021 // You should have received a copy of the GNU General Public License and
    00022 // a copy of the GCC Runtime Library Exception along with this program;
    00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00024 // <http://www.gnu.org/licenses/>.
    00025
    00026 /** @file concurrence.h
    00027  *  This is an internal header file, included by other library headers.
    00028  *  You should not attempt to use it directly.
    00029  */
    00030
    00031 #ifndef _CONCURRENCE_H
    00032 #define _CONCURRENCE_H 1
    00033
    00034 #include <exception>
    00035 #include <bits/gthr.h>
    00036 #include <bits/functexcept.h>
    00037
    00038 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
    00039
    00040   // Available locking policies:
    00041   // _S_single    single-threaded code that doesn't need to be locked.
    00042   // _S_mutex     multi-threaded code that requires additional support
    00043   //              from gthr.h or abstraction layers in concurrence.h.
    00044   // _S_atomic    multi-threaded code using atomic operations.
    00045   enum _Lock_policy { _S_single, _S_mutex, _S_atomic };
    00046
    00047   // Compile time constant that indicates prefered locking policy in
    00048   // the current configuration.
    00049   static const _Lock_policy __default_lock_policy =
    00050 #ifdef __GTHREADS
    00051 #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
    00052      && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))
    00053   _S_atomic;
    00054 #else
    00055   _S_mutex;
    00056 #endif
    00057 #else
    00058   _S_single;
    00059 #endif
    00060
    00061   // NB: As this is used in libsupc++, need to only depend on
    00062   // exception. No stdexception classes, no use of std::string.
    00063   class __concurrence_lock_error : public std::exception
    00064   {
    00065   public:
    00066     virtual char const*
    00067     what() const throw()
    00068     { return "__gnu_cxx::__concurrence_lock_error"; }
    00069   };
    00070
    00071   class __concurrence_unlock_error : public std::exception
    00072   {
    00073   public:
    00074     virtual char const*
    00075     what() const throw()
    00076     { return "__gnu_cxx::__concurrence_unlock_error"; }
    00077   };
    00078
    00079   class __concurrence_broadcast_error : public std::exception
    00080   {
    00081   public:
    00082     virtual char const*
    00083     what() const throw()
    00084     { return "__gnu_cxx::__concurrence_broadcast_error"; }
    00085   };
    00086
    00087   class __concurrence_wait_error : public std::exception
    00088   {
    00089   public:
    00090     virtual char const*
    00091     what() const throw()
    00092     { return "__gnu_cxx::__concurrence_wait_error"; }
    00093   };
    00094
    00095   // Substitute for concurrence_error object in the case of -fno-exceptions.
    00096   inline void
    00097   __throw_concurrence_lock_error()
    00098   {
    00099 #if __EXCEPTIONS
    00100     throw __concurrence_lock_error();
    00101 #else
    00102     __builtin_abort();
    00103 #endif
    00104   }
    00105
    00106   inline void
    00107   __throw_concurrence_unlock_error()
    00108   {
    00109 #if __EXCEPTIONS
    00110     throw __concurrence_unlock_error();
    00111 #else
    00112     __builtin_abort();
    00113 #endif
    00114   }
    00115
    00116 #ifdef __GTHREAD_HAS_COND
    00117   inline void
    00118   __throw_concurrence_broadcast_error()
    00119   {
    00120 #if __EXCEPTIONS
    00121     throw __concurrence_broadcast_error();
    00122 #else
    00123     __builtin_abort();
    00124 #endif
    00125   }
    00126
    00127   inline void
    00128   __throw_concurrence_wait_error()
    00129   {
    00130 #if __EXCEPTIONS
    00131     throw __concurrence_wait_error();
    00132 #else
    00133     __builtin_abort();
    00134 #endif
    00135   }
    00136 #endif
    00137
    00138   class __mutex
    00139   {
    00140   private:
    00141     __gthread_mutex_t _M_mutex;
    00142
    00143     __mutex(const __mutex&);
    00144     __mutex& operator=(const __mutex&);
    00145
    00146   public:
    00147     __mutex()
    00148     {
    00149 #if __GTHREADS
    00150       if (__gthread_active_p())
    00151     {
    00152 #if defined __GTHREAD_MUTEX_INIT
    00153       __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
    00154       _M_mutex = __tmp;
    00155 #else
    00156       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
    00157 #endif
    00158     }
    00159 #endif
    00160     }
    00161
    00162     void lock()
    00163     {
    00164 #if __GTHREADS
    00165       if (__gthread_active_p())
    00166     {
    00167       if (__gthread_mutex_lock(&_M_mutex) != 0)
    00168         __throw_concurrence_lock_error();
    00169     }
    00170 #endif
    00171     }
    00172
    00173     void unlock()
    00174     {
    00175 #if __GTHREADS
    00176       if (__gthread_active_p())
    00177     {
    00178       if (__gthread_mutex_unlock(&_M_mutex) != 0)
    00179         __throw_concurrence_unlock_error();
    00180     }
    00181 #endif
    00182     }
    00183
    00184     __gthread_mutex_t* gthread_mutex(void)
    00185       { return &_M_mutex; }
    00186   };
    00187
    00188   class __recursive_mutex
    00189   {
    00190   private:
    00191     __gthread_recursive_mutex_t _M_mutex;
    00192
    00193     __recursive_mutex(const __recursive_mutex&);
    00194     __recursive_mutex& operator=(const __recursive_mutex&);
    00195
    00196   public:
    00197     __recursive_mutex()
    00198     {
    00199 #if __GTHREADS
    00200       if (__gthread_active_p())
    00201     {
    00202 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
    00203       __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
    00204       _M_mutex = __tmp;
    00205 #else
    00206       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
    00207 #endif
    00208     }
    00209 #endif
    00210     }
    00211
    00212     void lock()
    00213     {
    00214 #if __GTHREADS
    00215       if (__gthread_active_p())
    00216     {
    00217       if (__gthread_recursive_mutex_lock(&_M_mutex) != 0)
    00218         __throw_concurrence_lock_error();
    00219     }
    00220 #endif
    00221     }
    00222
    00223     void unlock()
    00224     {
    00225 #if __GTHREADS
    00226       if (__gthread_active_p())
    00227     {
    00228       if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0)
    00229         __throw_concurrence_unlock_error();
    00230     }
    00231 #endif
    00232     }
    00233
    00234     __gthread_recursive_mutex_t* gthread_recursive_mutex(void)
    00235       { return &_M_mutex; }
    00236   };
    00237
    00238   /// Scoped lock idiom.
    00239   // Acquire the mutex here with a constructor call, then release with
    00240   // the destructor call in accordance with RAII style.
    00241   class __scoped_lock
    00242   {
    00243   public:
    00244     typedef __mutex __mutex_type;
    00245
    00246   private:
    00247     __mutex_type& _M_device;
    00248
    00249     __scoped_lock(const __scoped_lock&);
    00250     __scoped_lock& operator=(const __scoped_lock&);
    00251
    00252   public:
    00253     explicit __scoped_lock(__mutex_type& __name) : _M_device(__name)
    00254     { _M_device.lock(); }
    00255
    00256     ~__scoped_lock() throw()
    00257     { _M_device.unlock(); }
    00258   };
    00259
    00260 #ifdef __GTHREAD_HAS_COND
    00261   class __cond
    00262   {
    00263   private:
    00264     __gthread_cond_t _M_cond;
    00265
    00266     __cond(const __cond&);
    00267     __cond& operator=(const __cond&);
    00268
    00269   public:
    00270     __cond()
    00271     {
    00272 #if __GTHREADS
    00273       if (__gthread_active_p())
    00274     {
    00275 #if defined __GTHREAD_COND_INIT
    00276       __gthread_cond_t __tmp = __GTHREAD_COND_INIT;
    00277       _M_cond = __tmp;
    00278 #else
    00279       __GTHREAD_COND_INIT_FUNCTION(&_M_cond);
    00280 #endif
    00281     }
    00282 #endif
    00283     }
    00284
    00285     void broadcast()
    00286     {
    00287 #if __GTHREADS
    00288       if (__gthread_active_p())
    00289     {
    00290       if (__gthread_cond_broadcast(&_M_cond) != 0)
    00291         __throw_concurrence_broadcast_error();
    00292     }
    00293 #endif
    00294     }
    00295
    00296     void wait(__mutex *mutex)
    00297     {
    00298 #if __GTHREADS
    00299       {
    00300       if (__gthread_cond_wait(&_M_cond, mutex->gthread_mutex()) != 0)
    00301         __throw_concurrence_wait_error();
    00302       }
    00303 #endif
    00304     }
    00305
    00306     void wait_recursive(__recursive_mutex *mutex)
    00307     {
    00308 #if __GTHREADS
    00309       {
    00310       if (__gthread_cond_wait_recursive(&_M_cond,
    00311                         mutex->gthread_recursive_mutex())
    00312           != 0)
    00313         __throw_concurrence_wait_error();
    00314       }
    00315 #endif
    00316     }
    00317   };
    00318 #endif
    00319
    00320 _GLIBCXX_END_NAMESPACE
    00321
    00322 #endif