concurrence.h

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

Generated on Wed Mar 26 00:42:55 2008 for libstdc++ by  doxygen 1.5.1