00001 /* 00002 // $Id: //open/dev/fennel/synch/SXMutex.h#15 $ 00003 // Fennel is a library of data storage and processing components. 00004 // Copyright (C) 2005-2009 The Eigenbase Project 00005 // Copyright (C) 2005-2009 SQLstream, Inc. 00006 // Copyright (C) 2005-2009 LucidEra, Inc. 00007 // Portions Copyright (C) 1999-2009 John V. Sichi 00008 // 00009 // This program is free software; you can redistribute it and/or modify it 00010 // under the terms of the GNU General Public License as published by the Free 00011 // Software Foundation; either version 2 of the License, or (at your option) 00012 // any later version approved by The Eigenbase Project. 00013 // 00014 // This program is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with this program; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 */ 00023 00024 #ifndef Fennel_SXMutex_Included 00025 #define Fennel_SXMutex_Included 00026 00027 #include "fennel/synch/SynchMonitoredObject.h" 00028 #include "fennel/synch/LockHolderId.h" 00029 #include <boost/utility.hpp> 00030 00031 FENNEL_BEGIN_NAMESPACE 00032 00033 // NOTE jvs 25-Oct-2008: We can't replace this class with 00034 // boost::shared_mutex, because lock ownership need to be transaction-scoped 00035 // rather than thread-scoped. 00036 00053 class FENNEL_SYNCH_EXPORT SXMutex : public SynchMonitoredObject 00054 { 00055 public: 00059 enum SchedulingPolicy 00060 { 00065 SCHEDULE_DEFAULT, 00066 00075 SCHEDULE_FAVOR_EXCLUSIVE 00076 }; 00077 00078 explicit SXMutex(); 00079 ~SXMutex(); 00080 00081 bool waitFor( 00082 LockMode lockMode,uint iTimeout = ETERNITY, 00083 TxnId txnId = IMPLICIT_TXN_ID); 00084 void release(LockMode lockMode, TxnId txnId = IMPLICIT_TXN_ID); 00085 bool tryUpgrade(TxnId txnId = IMPLICIT_TXN_ID); 00086 00087 bool isLocked(LockMode lockdMode) const; 00088 void setSchedulingPolicy(SchedulingPolicy schedulingPolicy); 00089 00090 private: 00091 SchedulingPolicy schedulingPolicy; 00092 uint nShared,nExclusive,nExclusivePending; 00093 LockHolderId exclusiveHolderId; 00094 }; 00095 00101 template<LockMode lockMode> 00102 class SXMutexGuard : public boost::noncopyable 00103 { 00104 SXMutex &rwLock; 00105 bool m_locked; 00106 00107 public: 00108 explicit SXMutexGuard(SXMutex& mx, bool initially_locked = true) 00109 : rwLock(mx), m_locked(false) 00110 { 00111 if (initially_locked) { 00112 lock(); 00113 } 00114 } 00115 00116 ~SXMutexGuard() 00117 { 00118 if (m_locked) { 00119 unlock(); 00120 } 00121 } 00122 00123 void lock() 00124 { 00125 assert(!m_locked); 00126 rwLock.waitFor(lockMode); 00127 m_locked = true; 00128 } 00129 00130 void unlock() 00131 { 00132 assert(m_locked); 00133 rwLock.release(lockMode); 00134 m_locked = false; 00135 } 00136 00137 bool locked() const 00138 { 00139 return m_locked; 00140 } 00141 00142 operator const void*() const 00143 { 00144 return m_locked ? this : 0; 00145 } 00146 }; 00147 00148 typedef SXMutexGuard<LOCKMODE_S> SXMutexSharedGuard; 00149 typedef SXMutexGuard<LOCKMODE_X> SXMutexExclusiveGuard; 00150 00151 FENNEL_END_NAMESPACE 00152 00153 #endif 00154 00155 // End SXMutex.h