concurrence.h

Go to the documentation of this file.
00001 // Support for concurrent programing -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004, 2005, 2006
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 <cstdlib>
00040 #include <exception>
00041 #include <bits/gthr.h> 
00042 #include <bits/functexcept.h>
00043 
00044 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
00045 
00046   // Available locking policies:
00047   // _S_single    single-threaded code that doesn't need to be locked.
00048   // _S_mutex     multi-threaded code that requires additional support
00049   //              from gthr.h or abstraction layers in concurrence.h.
00050   // _S_atomic    multi-threaded code using atomic operations.
00051   enum _Lock_policy { _S_single, _S_mutex, _S_atomic }; 
00052 
00053   // Compile time constant that indicates prefered locking policy in
00054   // the current configuration.
00055   static const _Lock_policy __default_lock_policy = 
00056 #ifdef __GTHREADS
00057   // NB: This macro doesn't actually exist yet in the compiler, but is
00058   // set somewhat haphazardly at configure time.
00059 #ifdef _GLIBCXX_ATOMIC_BUILTINS
00060   _S_atomic;
00061 #else
00062   _S_mutex;
00063 #endif
00064 #else
00065   _S_single;
00066 #endif
00067   
00068   // NB: As this is used in libsupc++, need to only depend on
00069   // exception. No stdexception classes, no use of std::string.
00070   class __concurrence_lock_error : public std::exception
00071   {
00072   public:
00073     virtual char const*
00074     what() const throw()
00075     { return "__gnu_cxx::__concurrence_lock_error"; }
00076   };
00077 
00078   class __concurrence_unlock_error : public std::exception
00079   {
00080   public:
00081     virtual char const*
00082     what() const throw()
00083     { return "__gnu_cxx::__concurrence_unlock_error"; }
00084   };
00085 
00086   // Substitute for concurrence_error object in the case of -fno-exceptions.
00087   inline void
00088   __throw_concurrence_lock_error()
00089   {
00090 #if __EXCEPTIONS
00091     throw __concurrence_lock_error();
00092 #else
00093     std::abort();
00094 #endif
00095   }
00096 
00097   inline void
00098   __throw_concurrence_unlock_error()
00099   {
00100 #if __EXCEPTIONS
00101     throw __concurrence_unlock_error();
00102 #else
00103     std::abort();
00104 #endif
00105   }
00106 
00107   class __mutex 
00108   {
00109   private:
00110     __gthread_mutex_t _M_mutex;
00111 
00112     __mutex(const __mutex&);
00113     __mutex& operator=(const __mutex&);
00114 
00115   public:
00116     __mutex() 
00117     { 
00118 #if __GTHREADS
00119       if (__gthread_active_p())
00120     {
00121 #if defined __GTHREAD_MUTEX_INIT
00122       __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
00123       _M_mutex = __tmp;
00124 #else
00125       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); 
00126 #endif
00127     }
00128 #endif 
00129     }
00130 
00131     void lock()
00132     {
00133 #if __GTHREADS
00134       if (__gthread_active_p())
00135     {
00136       if (__gthread_mutex_lock(&_M_mutex) != 0)
00137         __throw_concurrence_lock_error();
00138     }
00139 #endif
00140     }
00141     
00142     void unlock()
00143     {
00144 #if __GTHREADS
00145       if (__gthread_active_p())
00146     {
00147       if (__gthread_mutex_unlock(&_M_mutex) != 0)
00148         __throw_concurrence_unlock_error();
00149     }
00150 #endif
00151     }
00152   };
00153 
00154   class __recursive_mutex 
00155   {
00156   private:
00157     __gthread_recursive_mutex_t _M_mutex;
00158 
00159     __recursive_mutex(const __recursive_mutex&);
00160     __recursive_mutex& operator=(const __recursive_mutex&);
00161 
00162   public:
00163     __recursive_mutex() 
00164     { 
00165 #if __GTHREADS
00166       if (__gthread_active_p())
00167     {
00168 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
00169       __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
00170       _M_mutex = __tmp;
00171 #else
00172       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 
00173 #endif
00174     }
00175 #endif 
00176     }
00177 
00178     void lock()
00179     { 
00180 #if __GTHREADS
00181       if (__gthread_active_p())
00182     {
00183       if (__gthread_recursive_mutex_lock(&_M_mutex) != 0)
00184         __throw_concurrence_lock_error();
00185     }
00186 #endif
00187     }
00188     
00189     void unlock()
00190     { 
00191 #if __GTHREADS
00192       if (__gthread_active_p())
00193     {
00194       if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0)
00195         __throw_concurrence_unlock_error();
00196     }
00197 #endif
00198     }
00199   };
00200 
00201   /// @brief  Scoped lock idiom.
00202   // Acquire the mutex here with a constructor call, then release with
00203   // the destructor call in accordance with RAII style.
00204   class __scoped_lock
00205   {
00206   public:
00207     typedef __mutex __mutex_type;
00208 
00209   private:
00210     __mutex_type& _M_device;
00211 
00212     __scoped_lock(const __scoped_lock&);
00213     __scoped_lock& operator=(const __scoped_lock&);
00214 
00215   public:
00216     explicit __scoped_lock(__mutex_type& __name) : _M_device(__name)
00217     { _M_device.lock(); }
00218 
00219     ~__scoped_lock() throw()
00220     { _M_device.unlock(); }
00221   };
00222 
00223 _GLIBCXX_END_NAMESPACE
00224 
00225 #endif

Generated on Thu Nov 1 13:11:23 2007 for libstdc++ by  doxygen 1.5.1