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

Generated on Thu Jul 23 21:16:02 2009 for libstdc++ by  doxygen 1.5.8