stl_threads.h

Go to the documentation of this file.
00001 // Threading support -*- C++ -*- 00002 00003 // Copyright (C) 2001 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 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 00130 // Locking class. Note that this class *does not have a 00131 // constructor*. It must be initialized either statically, with 00132 // __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling 00133 // the _M_initialize member function. (This is similar to the ways 00134 // that a pthreads mutex can be initialized.) There are explicit 00135 // member functions for acquiring and releasing the lock. 00136 00137 // There is no constructor because static initialization is 00138 // essential for some uses, and only a class aggregate (see section 00139 // 8.5.1 of the C++ standard) can be initialized that way. That 00140 // means we must have no constructors, no base classes, no virtual 00141 // functions, and no private or protected members. 00142 00143 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00144 extern __gthread_mutex_t _GLIBCPP_mutex; 00145 extern __gthread_mutex_t *_GLIBCPP_mutex_address; 00146 extern __gthread_once_t _GLIBCPP_once; 00147 extern void _GLIBCPP_mutex_init (void); 00148 extern void _GLIBCPP_mutex_address_init (void); 00149 #endif 00150 00151 struct _STL_mutex_lock 00152 { 00153 // The class must be statically initialized with __STL_MUTEX_INITIALIZER. 00154 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00155 volatile int _M_init_flag; 00156 __gthread_once_t _M_once; 00157 #endif 00158 __gthread_mutex_t _M_lock; 00159 00160 void 00161 _M_initialize() 00162 { 00163 #ifdef __GTHREAD_MUTEX_INIT 00164 // There should be no code in this path given the usage rules above. 00165 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00166 if (_M_init_flag) return; 00167 if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0 00168 && __gthread_active_p ()) 00169 abort (); 00170 __gthread_mutex_lock (&_GLIBCPP_mutex); 00171 if (!_M_init_flag) 00172 { 00173 // Even though we have a global lock, we use __gthread_once to be 00174 // absolutely certain the _M_lock mutex is only initialized once on 00175 // multiprocessor systems. 00176 _GLIBCPP_mutex_address = &_M_lock; 00177 if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0 00178 && __gthread_active_p ()) 00179 abort (); 00180 _M_init_flag = 1; 00181 } 00182 __gthread_mutex_unlock (&_GLIBCPP_mutex); 00183 #endif 00184 } 00185 00186 void 00187 _M_acquire_lock() 00188 { 00189 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00190 if (!_M_init_flag) _M_initialize(); 00191 #endif 00192 __gthread_mutex_lock(&_M_lock); 00193 } 00194 00195 void 00196 _M_release_lock() 00197 { 00198 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00199 if (!_M_init_flag) _M_initialize(); 00200 #endif 00201 __gthread_mutex_unlock(&_M_lock); 00202 } 00203 }; 00204 00205 #ifdef __GTHREAD_MUTEX_INIT 00206 #define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT } 00207 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 00208 #ifdef __GTHREAD_MUTEX_INIT_DEFAULT 00209 #define __STL_MUTEX_INITIALIZER \ 00210 = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT } 00211 #else 00212 #define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT } 00213 #endif 00214 #endif 00215 00216 // A locking class that uses _STL_mutex_lock. The constructor takes a 00217 // reference to an _STL_mutex_lock, and acquires a lock. The 00218 // destructor releases the lock. It's not clear that this is exactly 00219 // the right functionality. It will probably change in the future. 00220 struct _STL_auto_lock 00221 { 00222 _STL_mutex_lock& _M_lock; 00223 00224 _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock) 00225 { _M_lock._M_acquire_lock(); } 00226 00227 ~_STL_auto_lock() { _M_lock._M_release_lock(); } 00228 00229 private: 00230 void operator=(const _STL_auto_lock&); 00231 _STL_auto_lock(const _STL_auto_lock&); 00232 }; 00233 00234 } // namespace std 00235 00236 #endif

Generated on Wed Sep 29 13:54:53 2004 for libstdc++-v3 Source by doxygen 1.3.7