00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00036 #include "OW_config.h"
00037 #include "OW_RWLocker.hpp"
00038 #include "OW_Assertion.hpp"
00039 #include "OW_ThreadImpl.hpp"
00040 #include "OW_TimeoutException.hpp"
00041 #include "OW_ExceptionIds.hpp"
00042
00043 namespace OW_NAMESPACE
00044 {
00045
00046 OW_DEFINE_EXCEPTION_WITH_ID(RWLocker);
00048 RWLocker::RWLocker()
00049 : m_waiting_writers()
00050 , m_waiting_readers()
00051 , m_num_waiting_writers(0)
00052 , m_num_waiting_readers(0)
00053 , m_readers_next(0)
00054 , m_guard()
00055 , m_state(0)
00056 {
00057 }
00059 RWLocker::~RWLocker()
00060 {
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 }
00072 void
00073 RWLocker::getReadLock(UInt32 sTimeout, UInt32 usTimeout)
00074 {
00075 NonRecursiveMutexLock l(m_guard);
00076
00077
00078
00079
00080
00081
00082 Thread_t tid = ThreadImpl::currentThread();
00083 if (m_state < 0)
00084 {
00085
00086 if (ThreadImpl::sameThreads(m_writer, tid))
00087 {
00088 OW_THROW(DeadlockException, "A thread that has a write lock is trying to acquire a read lock.");
00089 }
00090 }
00091 while (m_state < 0)
00092 {
00093 ++m_num_waiting_readers;
00094
00095 if (!m_waiting_readers.timedWait(l, sTimeout, usTimeout))
00096 {
00097 --m_num_waiting_readers;
00098 OW_THROW(TimeoutException, "Timeout while waiting for read lock.");
00099 }
00100 --m_num_waiting_readers;
00101 }
00102
00103
00104 m_state++;
00105 m_readers.push_back(tid);
00106 }
00108 void
00109 RWLocker::getWriteLock(UInt32 sTimeout, UInt32 usTimeout)
00110 {
00111 NonRecursiveMutexLock l(m_guard);
00112
00113
00114
00115
00116
00117 Thread_t tid = ThreadImpl::currentThread();
00118 if (m_state != 0)
00119 {
00120
00121 for (size_t i = 0; i < m_readers.size(); ++i)
00122 {
00123 if (ThreadImpl::sameThreads(m_readers[i], tid))
00124 {
00125 OW_THROW(DeadlockException, "A thread that has a read lock is trying to acquire a write lock.");
00126 }
00127 }
00128 }
00129 while (m_state != 0)
00130 {
00131 ++m_num_waiting_writers;
00132 if (!m_waiting_writers.timedWait(l, sTimeout, usTimeout))
00133 {
00134 --m_num_waiting_writers;
00135 OW_THROW(TimeoutException, "Timeout while waiting for write lock.");
00136 }
00137 --m_num_waiting_writers;
00138 }
00139 m_state = -1;
00140 m_writer = tid;
00141 }
00143 void
00144 RWLocker::releaseReadLock()
00145 {
00146 NonRecursiveMutexLock l(m_guard);
00147 if (m_state > 0)
00148 --m_state;
00149 else
00150 OW_THROW(RWLockerException, "A writer is releasing a read lock");
00151 if (m_state == 0)
00152 {
00153 doWakeups();
00154 }
00155 Thread_t tid = ThreadImpl::currentThread();
00156 size_t i = 0;
00157 while (i < m_readers.size())
00158 {
00159 if (ThreadImpl::sameThreads(m_readers[i], tid))
00160 {
00161 m_readers.remove(i);
00162 }
00163 else
00164 {
00165 ++i;
00166 }
00167 }
00168 }
00170 void
00171 RWLocker::releaseWriteLock()
00172 {
00173 NonRecursiveMutexLock l(m_guard);
00174 if (m_state == -1)
00175 {
00176 m_state = 0;
00177 }
00178 else
00179 {
00180 OW_THROW(RWLockerException, "A reader is releasing a write lock");
00181 }
00182
00183
00184 doWakeups();
00185 }
00187 void
00188 RWLocker::doWakeups()
00189 {
00190 if ( m_num_waiting_writers > 0 &&
00191 m_num_waiting_readers > 0)
00192 {
00193 if (m_readers_next == 1)
00194 {
00195 m_readers_next = 0;
00196 m_waiting_readers.notifyAll();
00197 }
00198 else
00199 {
00200 m_waiting_writers.notifyOne();
00201 m_readers_next = 1;
00202 }
00203 }
00204 else if (m_num_waiting_writers > 0)
00205 {
00206
00207 m_waiting_writers.notifyOne();
00208 }
00209 else if (m_num_waiting_readers > 0)
00210 {
00211
00212 m_waiting_readers.notifyAll();
00213 }
00214 }
00215
00216 }
00217