1 // Threading support -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // You should have received a copy of the GNU General Public License along 17 // with this library; see the file COPYING. If not, write to the Free 18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19 // USA. 20 21 // As a special exception, you may use this file as part of a free software 22 // library without restriction. Specifically, if other files instantiate 23 // templates or use macros or inline functions from this file, or you compile 24 // this file and link it with other files to produce an executable, this 25 // file does not by itself cause the resulting executable to be covered by 26 // the GNU General Public License. This exception does not however 27 // invalidate any other reasons why the executable file might be covered by 28 // the GNU General Public License. 29 30 /* 31 * Copyright (c) 1997-1999 32 * Silicon Graphics Computer Systems, Inc. 33 * 34 * Permission to use, copy, modify, distribute and sell this software 35 * and its documentation for any purpose is hereby granted without fee, 36 * provided that the above copyright notice appear in all copies and 37 * that both that copyright notice and this permission notice appear 38 * in supporting documentation. Silicon Graphics makes no 39 * representations about the suitability of this software for any 40 * purpose. It is provided "as is" without express or implied warranty. 41 */ 42 43 /** @file stl_threads.h 44 * This is an internal header file, included by other library headers. 45 * You should not attempt to use it directly. 46 */ 47 48 #ifndef _STL_THREADS_H 49 #define _STL_THREADS_H 1 50 51 #include <cstddef> 52 53 // The only supported threading model is GCC's own gthr.h abstraction 54 // layer. 55 #include "bits/gthr.h" 56 57 namespace __gnu_internal 58 { 59 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 60 extern __gthread_mutex_t _GLIBCXX_mutex; 61 extern __gthread_mutex_t *_GLIBCXX_mutex_address; 62 extern __gthread_once_t _GLIBCXX_once; 63 extern void _GLIBCXX_mutex_init(void); 64 extern void _GLIBCXX_mutex_address_init(void); 65 #endif 66 } // namespace __gnu_internal 67 68 namespace __gnu_cxx 69 { 70 // Locking class. Note that this class *does not have a 71 // constructor*. It must be initialized either statically, with 72 // __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling 73 // the _M_initialize member function. (This is similar to the ways 74 // that a pthreads mutex can be initialized.) There are explicit 75 // member functions for acquiring and releasing the lock. 76 77 // There is no constructor because static initialization is 78 // essential for some uses, and only a class aggregate (see section 79 // 8.5.1 of the C++ standard) can be initialized that way. That 80 // means we must have no constructors, no base classes, no virtual 81 // functions, and no private or protected members. 82 struct _STL_mutex_lock 83 { 84 // The class must be statically initialized with __STL_MUTEX_INITIALIZER. 85 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 86 volatile int _M_init_flag; 87 __gthread_once_t _M_once; 88 #endif 89 __gthread_mutex_t _M_lock; 90 91 void _M_initialize_STL_mutex_lock92 _M_initialize() 93 { 94 #ifdef __GTHREAD_MUTEX_INIT 95 // There should be no code in this path given the usage rules above. 96 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 97 if (_M_init_flag) return; 98 if (__gthread_once(&__gnu_internal::_GLIBCXX_once, 99 __gnu_internal::_GLIBCXX_mutex_init) != 0 100 && __gthread_active_p()) 101 abort (); 102 __gthread_mutex_lock(&__gnu_internal::_GLIBCXX_mutex); 103 if (!_M_init_flag) 104 { 105 // Even though we have a global lock, we use __gthread_once to be 106 // absolutely certain the _M_lock mutex is only initialized once on 107 // multiprocessor systems. 108 __gnu_internal::_GLIBCXX_mutex_address = &_M_lock; 109 if (__gthread_once(&_M_once, 110 __gnu_internal::_GLIBCXX_mutex_address_init) != 0 111 && __gthread_active_p()) 112 abort(); 113 _M_init_flag = 1; 114 } 115 __gthread_mutex_unlock(&__gnu_internal::_GLIBCXX_mutex); 116 #endif 117 } 118 119 void _M_acquire_lock_STL_mutex_lock120 _M_acquire_lock() 121 { 122 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 123 if (!_M_init_flag) _M_initialize(); 124 #endif 125 __gthread_mutex_lock(&_M_lock); 126 } 127 128 void _M_release_lock_STL_mutex_lock129 _M_release_lock() 130 { 131 #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) 132 if (!_M_init_flag) _M_initialize(); 133 #endif 134 __gthread_mutex_unlock(&_M_lock); 135 } 136 }; 137 138 #ifdef __GTHREAD_MUTEX_INIT 139 #define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT } 140 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) 141 #ifdef __GTHREAD_MUTEX_INIT_DEFAULT 142 #define __STL_MUTEX_INITIALIZER \ 143 = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT } 144 #else 145 #define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT } 146 #endif 147 #endif 148 } // namespace __gnu_cxx 149 150 #endif 151