00001 /* -*- mode:C++; c-basic-offset:4 -*- 00002 Shore-MT -- Multi-threaded port of the SHORE storage manager 00003 00004 Copyright (c) 2007-2009 00005 Data Intensive Applications and Systems Labaratory (DIAS) 00006 Ecole Polytechnique Federale de Lausanne 00007 00008 All Rights Reserved. 00009 00010 Permission to use, copy, modify and distribute this software and 00011 its documentation is hereby granted, provided that both the 00012 copyright notice and this permission notice appear in all copies of 00013 the software, derivative works or modified versions, and any 00014 portions thereof, and that both notices appear in supporting 00015 documentation. 00016 00017 This code is distributed in the hope that it will be useful, but 00018 WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS 00020 DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 00021 RESULTING FROM THE USE OF THIS SOFTWARE. 00022 */ 00023 00024 // -*- mode:c++; c-basic-offset:4 -*- 00025 /*<std-header orig-src='shore' incl-file-exclusion='STHREAD_H'> 00026 00027 $Id: critical_section.h,v 1.2 2011/09/08 18:11:01 nhall Exp $ 00028 00029 SHORE -- Scalable Heterogeneous Object REpository 00030 00031 Copyright (c) 1994-99 Computer Sciences Department, University of 00032 Wisconsin -- Madison 00033 All Rights Reserved. 00034 00035 Permission to use, copy, modify and distribute this software and its 00036 documentation is hereby granted, provided that both the copyright 00037 notice and this permission notice appear in all copies of the 00038 software, derivative works or modified versions, and any portions 00039 thereof, and that both notices appear in supporting documentation. 00040 00041 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY 00042 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS 00043 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND 00044 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 00045 00046 This software was developed with support by the Advanced Research 00047 Project Agency, ARPA order number 018 (formerly 8230), monitored by 00048 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518. 00049 Further funding for this work was provided by DARPA through 00050 Rome Research Laboratory Contract No. F30602-97-2-0247. 00051 00052 */ 00053 00054 /* -- do not edit anything above this line -- </std-header>*/ 00055 00056 #ifndef CRIT_SEC_H 00057 #define CRIT_SEC_H 00058 00059 /**\def CRITICAL_SECTION(name, lock) 00060 * 00061 * This macro starts a critical section protected by the given lock 00062 * (2nd argument). The critical_section structure it creates is 00063 * named by the 1st argument. 00064 * The rest of the scope (in which this macro is used) becomes the 00065 * scope of the critical section, since it is the destruction of this 00066 * critical_section structure that releases the lock. 00067 * 00068 * The programmer can release the lock early by calling <name>.pause() 00069 * or <name>.exit(). 00070 * The programmer can reacquire the lock by calling <name>.resume() if 00071 * <name>.pause() was called, but not after <name>.exit(). 00072 * 00073 * \sa critical_section 00074 */ 00075 #define CRITICAL_SECTION(name, lock) critical_section<__typeof__(lock)&> name(lock) 00076 00077 template<class Lock> 00078 struct critical_section; 00079 00080 /**\brief Helper class for CRITICAL_SECTION idiom (macro). 00081 * 00082 * This templated class does nothing; its various specializations 00083 * do the work of acquiring the given lock upon construction and 00084 * releasing it upon destruction. 00085 * See the macros: 00086 * - SPECIALIZE_CS(Lock, Extra, ExtraInit, Acquire, Release) 00087 * - CRITICAL_SECTION(name, lock) 00088 */ 00089 template<class Lock> 00090 struct critical_section<Lock*&> : public critical_section<Lock&> { 00091 critical_section<Lock*&>(Lock* mutex) : critical_section<Lock&>(*mutex) { } 00092 }; 00093 00094 /* 00095 * NOTE: I added ExtraInit to make the initialization happen so that 00096 * assertions about holding the mutex don't fail. 00097 * At the same time, I added a holder to the w_pthread_lock_t 00098 * implementation so I could make assertions about the holder outside 00099 * the lock implementation itself. This might seem like doubly 00100 * asserting, but in the cases where the critical section isn't 00101 * based on a pthread mutex, we really should have this clean 00102 * initialization and the check the assertions. 00103 */ 00104 00105 /**\def SPECIALIZE_CS(Lock, Extra, ExtraInit, Acquire, Release) 00106 * \brief Macro that enables use of CRITICAL_SECTION(name,lock) 00107 *\addindex SPECIALIZE_CS 00108 * 00109 * \details 00110 * Create a templated class that holds 00111 * - a reference to the given lock and 00112 * - the Extra (2nd macro argument) 00113 * 00114 * and it 00115 * - applies the ExtraInit and Acquire commands upon construction, 00116 * - applies the Release command upon destruction. 00117 * 00118 * pointer() is here for debugging: w_assert0(pointer()); can be 00119 * placed before ExtraInit or elsewhere. It was needed to track down 00120 * gcc44 optimizer bug, which had the symptom that it seemed that 00121 * the destructor for critical_section wasn't being called, when 00122 * in fact the problem was that the _mutex variable wasn't being set. 00123 */ 00124 #define SPECIALIZE_CS(Lock,Extra,ExtraInit,Acquire,Release) \ 00125 template<> struct critical_section<Lock&> { \ 00126 critical_section(Lock &mutex) \ 00127 : _mutex(&mutex) \ 00128 { ExtraInit; Acquire; } \ 00129 ~critical_section() { \ 00130 if(_mutex) \ 00131 Release; \ 00132 _mutex = NULL; \ 00133 } \ 00134 void pause() { Release; } \ 00135 bool pointer() { return _mutex!=NULL; } \ 00136 void resume() { Acquire; }\ 00137 void exit() { Release; _mutex = NULL; } \ 00138 Lock &hand_off() { \ 00139 Lock* rval = _mutex; \ 00140 _mutex = NULL; \ 00141 return *rval; \ 00142 } \ 00143 private: \ 00144 Lock* GCC4_WORKAROUND_1 _mutex; \ 00145 Extra; \ 00146 void operator=(critical_section const &); \ 00147 critical_section(critical_section const &); \ 00148 } 00149 00150 00151 // I undef-ed this and found all occurrances of CRITICAL_SECTION with this. 00152 // and hand-checked them. 00153 SPECIALIZE_CS(pthread_mutex_t, int _dummy, (_dummy=0), 00154 pthread_mutex_lock(_mutex), pthread_mutex_unlock(_mutex)); 00155 00156 00157 #endif /*</std-footer>*/