Apache Qpid - AMQP Messaging for Java JMS, C++, Python, Ruby, and .NET | Apache Qpid Documentation |
00001 #ifndef _sys_windows_Mutex_h 00002 #define _sys_windows_Mutex_h 00003 00004 /* 00005 * 00006 * Copyright (c) 2008 The Apache Software Foundation 00007 * 00008 * Licensed under the Apache License, Version 2.0 (the "License"); 00009 * you may not use this file except in compliance with the License. 00010 * You may obtain a copy of the License at 00011 * 00012 * http://www.apache.org/licenses/LICENSE-2.0 00013 * 00014 * Unless required by applicable law or agreed to in writing, software 00015 * distributed under the License is distributed on an "AS IS" BASIS, 00016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00017 * See the License for the specific language governing permissions and 00018 * limitations under the License. 00019 * 00020 */ 00021 00022 #include "qpid/sys/windows/check.h" 00023 00024 #include <boost/version.hpp> 00025 #if (BOOST_VERSION < 103500) 00026 #error The Windows port requires Boost version 1.35.0 or later 00027 #endif 00028 00029 #include <boost/noncopyable.hpp> 00030 #include <boost/thread/recursive_mutex.hpp> 00031 #include <boost/thread/shared_mutex.hpp> 00032 #include <boost/thread/thread_time.hpp> 00033 #include <boost/thread/tss.hpp> 00034 00035 namespace qpid { 00036 namespace sys { 00037 00038 class Condition; 00039 00043 class Mutex : private boost::noncopyable { 00044 friend class Condition; 00045 00046 public: 00047 typedef ::qpid::sys::ScopedLock<Mutex> ScopedLock; 00048 typedef ::qpid::sys::ScopedUnlock<Mutex> ScopedUnlock; 00049 00050 inline Mutex(); 00051 inline ~Mutex(); 00052 inline void lock(); 00053 inline void unlock(); 00054 inline bool trylock(); 00055 00056 00057 protected: 00058 boost::recursive_mutex mutex; 00059 }; 00060 00064 class RWlock : private boost::noncopyable { 00065 friend class Condition; 00066 00067 public: 00068 typedef ::qpid::sys::ScopedRlock<RWlock> ScopedRlock; 00069 typedef ::qpid::sys::ScopedWlock<RWlock> ScopedWlock; 00070 00071 inline RWlock(); 00072 inline ~RWlock(); 00073 inline void wlock(); // will write-lock 00074 inline void rlock(); // will read-lock 00075 inline void unlock(); 00076 inline void trywlock(); // will write-try 00077 inline void tryrlock(); // will read-try 00078 00079 protected: 00080 boost::shared_mutex rwMutex; 00081 boost::thread_specific_ptr<bool> haveWrite; 00082 00083 inline bool &write (void); 00084 }; 00085 00086 00091 struct PODMutex 00092 { 00093 typedef ::qpid::sys::ScopedLock<PODMutex> ScopedLock; 00094 00095 inline void lock(); 00096 inline void unlock(); 00097 inline bool trylock(); 00098 00099 // Must be public to be a POD: 00100 boost::recursive_mutex mutex; 00101 }; 00102 00103 #define QPID_MUTEX_INITIALIZER 0 00104 00105 void PODMutex::lock() { 00106 mutex.lock(); 00107 } 00108 00109 void PODMutex::unlock() { 00110 mutex.unlock(); 00111 } 00112 00113 bool PODMutex::trylock() { 00114 return mutex.try_lock(); 00115 } 00116 00117 Mutex::Mutex() { 00118 } 00119 00120 Mutex::~Mutex(){ 00121 } 00122 00123 void Mutex::lock() { 00124 mutex.lock(); 00125 } 00126 00127 void Mutex::unlock() { 00128 mutex.unlock(); 00129 } 00130 00131 bool Mutex::trylock() { 00132 return mutex.try_lock(); 00133 } 00134 00135 00136 RWlock::RWlock() { 00137 } 00138 00139 RWlock::~RWlock(){ 00140 } 00141 00142 void RWlock::wlock() { 00143 bool &writer = write(); 00144 rwMutex.lock(); 00145 writer = true; // Remember this thread has write lock held. 00146 } 00147 00148 void RWlock::rlock() { 00149 bool &writer = write(); 00150 rwMutex.lock_shared(); 00151 writer = false; // Remember this thread has shared lock held. 00152 } 00153 00154 void RWlock::unlock() { 00155 bool &writer = write(); 00156 if (writer) 00157 rwMutex.unlock(); 00158 else 00159 rwMutex.unlock_shared(); 00160 } 00161 00162 void RWlock::trywlock() { 00163 bool &writer = write(); 00164 // shared_mutex::try_lock() seems to not be available... emulate it with 00165 // a timed lock(). 00166 boost::system_time now = boost::get_system_time(); 00167 if (rwMutex.timed_lock(now)) 00168 writer = true; 00169 } 00170 00171 void RWlock::tryrlock() { 00172 bool &writer = write(); 00173 if (rwMutex.try_lock_shared()) 00174 writer = false; 00175 } 00176 00177 bool & RWlock::write (void) { 00178 // Accessing thread-specific and stack-local info, so no locks needed. 00179 bool *writePtr = haveWrite.get(); 00180 if (writePtr == 0) { 00181 writePtr = new bool(false); 00182 haveWrite.reset(writePtr); 00183 } 00184 return *writePtr; 00185 } 00186 00187 }} 00188 #endif