stl_threads.h

Go to the documentation of this file.
00001 // Threading support -*- C++ -*- 00002 00003 // Copyright (C) 2001, 2002 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 2, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // You should have received a copy of the GNU General Public License along 00017 // with this library; see the file COPYING. If not, write to the Free 00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00019 // USA. 00020 00021 // As a special exception, you may use this file as part of a free software 00022 // library without restriction. Specifically, if other files instantiate 00023 // templates or use macros or inline functions from this file, or you compile 00024 // this file and link it with other files to produce an executable, this 00025 // file does not by itself cause the resulting executable to be covered by 00026 // the GNU General Public License. This exception does not however 00027 // invalidate any other reasons why the executable file might be covered by 00028 // the GNU General Public License. 00029 00030 /* 00031 * Copyright (c) 1997-1999 00032 * Silicon Graphics Computer Systems, Inc. 00033 * 00034 * Permission to use, copy, modify, distribute and sell this software 00035 * and its documentation for any purpose is hereby granted without fee, 00036 * provided that the above copyright notice appear in all copies and 00037 * that both that copyright notice and this permission notice appear 00038 * in supporting documentation. Silicon Graphics makes no 00039 * representations about the suitability of this software for any 00040 * purpose. It is provided "as is" without express or implied warranty. 00041 */ 00042 00043 /** @file stl_threads.h 00044 * This is an internal header file, included by other library headers. 00045 * You should not attempt to use it directly. 00046 */ 00047 00048 #ifndef __SGI_STL_INTERNAL_THREADS_H 00049 #define __SGI_STL_INTERNAL_THREADS_H 00050 00051 // The only supported threading model is GCC's own gthr.h abstraction layer. 00052 #include "bits/gthr.h" 00053 00054 namespace std 00055 { 00056 // Class _Refcount_Base provides a type, _RC_t, a data member, 00057 // _M_ref_count, and member functions _M_incr and _M_decr, which perform 00058 // atomic preincrement/predecrement. The constructor initializes 00059 // _M_ref_count. 00060 struct _Refcount_Base 00061 { 00062 // The type _RC_t 00063 typedef size_t _RC_t; 00064 00065 // The data member _M_ref_count 00066 volatile _RC_t _M_ref_count; 00067 00068 // Constructor 00069 __gthread_mutex_t _M_ref_count_lock; 00070 00071 _Refcount_Base(_RC_t __n) : _M_ref_count(__n) 00072 { 00073 #ifdef __GTHREAD_MUTEX_INIT 00074 __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; 00075 _M_ref_count_lock = __tmp; 00076 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00077 __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock); 00078 #else 00079 #error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org. 00080 #endif 00081 } 00082 00083 void 00084 _M_incr() 00085 { 00086 __gthread_mutex_lock(&_M_ref_count_lock); 00087 ++_M_ref_count; 00088 __gthread_mutex_unlock(&_M_ref_count_lock); 00089 } 00090 00091 _RC_t 00092 _M_decr() 00093 { 00094 __gthread_mutex_lock(&_M_ref_count_lock); 00095 volatile _RC_t __tmp = --_M_ref_count; 00096 __gthread_mutex_unlock(&_M_ref_count_lock); 00097 return __tmp; 00098 } 00099 }; 00100 00101 // Atomic swap on unsigned long 00102 // This is guaranteed to behave as though it were atomic only if all 00103 // possibly concurrent updates use _Atomic_swap. 00104 // In some cases the operation is emulated with a lock. 00105 #if defined (__GTHREAD_MUTEX_INIT) 00106 // This could be optimized to use the atomicity.h abstraction layer. 00107 // vyzo: simple _Atomic_swap implementation following the guidelines above 00108 // We use a template here only to get a unique initialized instance. 00109 template<int __dummy> 00110 struct _Swap_lock_struct 00111 { static __gthread_mutex_t _S_swap_lock; }; 00112 00113 template<int __dummy> 00114 __gthread_mutex_t 00115 _Swap_lock_struct<__dummy>::_S_swap_lock = __GTHREAD_MUTEX_INIT; 00116 00117 // This should be portable, but performance is expected to be quite 00118 // awful. This really needs platform specific code. 00119 inline unsigned long 00120 _Atomic_swap(unsigned long * __p, unsigned long __q) 00121 { 00122 __gthread_mutex_lock(&_Swap_lock_struct<0>::_S_swap_lock); 00123 unsigned long __result = *__p; 00124 *__p = __q; 00125 __gthread_mutex_unlock(&_Swap_lock_struct<0>::_S_swap_lock); 00126 return __result; 00127 } 00128 #endif 00129 } //namespace std 00130 00131 // Locking class. Note that this class *does not have a 00132 // constructor*. It must be initialized either statically, with 00133 // __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling 00134 // the _M_initialize member function. (This is similar to the ways 00135 // that a pthreads mutex can be initialized.) There are explicit 00136 // member functions for acquiring and releasing the lock. 00137 00138 // There is no constructor because static initialization is 00139 // essential for some uses, and only a class aggregate (see section 00140 // 8.5.1 of the C++ standard) can be initialized that way. That 00141 // means we must have no constructors, no base classes, no virtual 00142 // functions, and no private or protected members. 00143 00144 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00145 namespace __gnu_cxx 00146 { 00147 extern __gthread_mutex_t _GLIBCPP_mutex; 00148 extern __gthread_mutex_t *_GLIBCPP_mutex_address; 00149 extern __gthread_once_t _GLIBCPP_once; 00150 extern void _GLIBCPP_mutex_init (void); 00151 extern void _GLIBCPP_mutex_address_init (void); 00152 } 00153 #endif 00154 00155 namespace std 00156 { 00157 struct _STL_mutex_lock 00158 { 00159 // The class must be statically initialized with __STL_MUTEX_INITIALIZER. 00160 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00161 volatile int _M_init_flag; 00162 __gthread_once_t _M_once; 00163 #endif 00164 __gthread_mutex_t _M_lock; 00165 00166 void 00167 _M_initialize() 00168 { 00169 #ifdef __GTHREAD_MUTEX_INIT 00170 // There should be no code in this path given the usage rules above. 00171 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00172 if (_M_init_flag) return; 00173 if (__gthread_once (&__gnu_cxx::_GLIBCPP_once, 00174 __gnu_cxx::_GLIBCPP_mutex_init) != 0 00175 && __gthread_active_p ()) 00176 abort (); 00177 __gthread_mutex_lock (&__gnu_cxx::_GLIBCPP_mutex); 00178 if (!_M_init_flag) 00179 { 00180 // Even though we have a global lock, we use __gthread_once to be 00181 // absolutely certain the _M_lock mutex is only initialized once on 00182 // multiprocessor systems. 00183 __gnu_cxx::_GLIBCPP_mutex_address = &_M_lock; 00184 if (__gthread_once (&_M_once, 00185 __gnu_cxx::_GLIBCPP_mutex_address_init) != 0 00186 && __gthread_active_p ()) 00187 abort (); 00188 _M_init_flag = 1; 00189 } 00190 __gthread_mutex_unlock (&__gnu_cxx::_GLIBCPP_mutex); 00191 #endif 00192 } 00193 00194 void 00195 _M_acquire_lock() 00196 { 00197 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00198 if (!_M_init_flag) _M_initialize(); 00199 #endif 00200 __gthread_mutex_lock(&_M_lock); 00201 } 00202 00203 void 00204 _M_release_lock() 00205 { 00206 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00207 if (!_M_init_flag) _M_initialize(); 00208 #endif 00209 __gthread_mutex_unlock(&_M_lock); 00210 } 00211 }; 00212 00213 #ifdef __GTHREAD_MUTEX_INIT 00214 #define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT } 00215 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00216 #ifdef __GTHREAD_MUTEX_INIT_DEFAULT 00217 #define __STL_MUTEX_INITIALIZER \ 00218 = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT } 00219 #else 00220 #define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT } 00221 #endif 00222 #endif 00223 00224 // A locking class that uses _STL_mutex_lock. The constructor takes a 00225 // reference to an _STL_mutex_lock, and acquires a lock. The 00226 // destructor releases the lock. It's not clear that this is exactly 00227 // the right functionality. It will probably change in the future. 00228 struct _STL_auto_lock 00229 { 00230 _STL_mutex_lock& _M_lock; 00231 00232 _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock) 00233 { _M_lock._M_acquire_lock(); } 00234 00235 ~_STL_auto_lock() { _M_lock._M_release_lock(); } 00236 00237 private: 00238 void operator=(const _STL_auto_lock&); 00239 _STL_auto_lock(const _STL_auto_lock&); 00240 }; 00241 00242 } // namespace std 00243 00244 #endif

Generated on Sun Sep 19 16:34:02 2004 for libstdc++-v3 Source by doxygen 1.3.8