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
00031
00032
00033
00034
00035
00036
00037 #include "Poco/RWLock_WIN32.h"
00038
00039
00040 namespace Poco {
00041
00042
00043 RWLockImpl::RWLockImpl(): _readers(0), _writersWaiting(0), _writers(0)
00044 {
00045 _mutex = CreateMutexW(NULL, FALSE, NULL);
00046 if (_mutex == NULL)
00047 throw SystemException("cannot create reader/writer lock");
00048
00049 _readEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
00050 if (_readEvent == NULL)
00051 throw SystemException("cannot create reader/writer lock");
00052
00053 _writeEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
00054 if (_writeEvent == NULL)
00055 throw SystemException("cannot create reader/writer lock");
00056 }
00057
00058
00059 RWLockImpl::~RWLockImpl()
00060 {
00061 CloseHandle(_mutex);
00062 CloseHandle(_readEvent);
00063 CloseHandle(_writeEvent);
00064 }
00065
00066
00067 inline void RWLockImpl::addWriter()
00068 {
00069 switch (WaitForSingleObject(_mutex, INFINITE))
00070 {
00071 case WAIT_OBJECT_0:
00072 if (++_writersWaiting == 1) ResetEvent(_readEvent);
00073 ReleaseMutex(_mutex);
00074 break;
00075 default:
00076 throw SystemException("cannot lock reader/writer lock");
00077 }
00078 }
00079
00080
00081 inline void RWLockImpl::removeWriter()
00082 {
00083 switch (WaitForSingleObject(_mutex, INFINITE))
00084 {
00085 case WAIT_OBJECT_0:
00086 if (--_writersWaiting == 0 && _writers == 0) SetEvent(_readEvent);
00087 ReleaseMutex(_mutex);
00088 break;
00089 default:
00090 throw SystemException("cannot lock reader/writer lock");
00091 }
00092 }
00093
00094
00095 void RWLockImpl::readLockImpl()
00096 {
00097 HANDLE h[2];
00098 h[0] = _mutex;
00099 h[1] = _readEvent;
00100 switch (WaitForMultipleObjects(2, h, TRUE, INFINITE))
00101 {
00102 case WAIT_OBJECT_0:
00103 case WAIT_OBJECT_0 + 1:
00104 ++_readers;
00105 ResetEvent(_writeEvent);
00106 ReleaseMutex(_mutex);
00107 poco_assert_dbg(_writers == 0);
00108 break;
00109 default:
00110 throw SystemException("cannot lock reader/writer lock");
00111 }
00112 }
00113
00114
00115 bool RWLockImpl::tryReadLockImpl()
00116 {
00117 HANDLE h[2];
00118 h[0] = _mutex;
00119 h[1] = _readEvent;
00120 switch (WaitForMultipleObjects(2, h, TRUE, 1))
00121 {
00122 case WAIT_OBJECT_0:
00123 case WAIT_OBJECT_0 + 1:
00124 ++_readers;
00125 ResetEvent(_writeEvent);
00126 ReleaseMutex(_mutex);
00127 poco_assert_dbg(_writers == 0);
00128 return true;
00129 case WAIT_TIMEOUT:
00130 return false;
00131 default:
00132 throw SystemException("cannot lock reader/writer lock");
00133 }
00134 }
00135
00136
00137 void RWLockImpl::writeLockImpl()
00138 {
00139 addWriter();
00140 HANDLE h[2];
00141 h[0] = _mutex;
00142 h[1] = _writeEvent;
00143 switch (WaitForMultipleObjects(2, h, TRUE, INFINITE))
00144 {
00145 case WAIT_OBJECT_0:
00146 case WAIT_OBJECT_0 + 1:
00147 --_writersWaiting;
00148 ++_readers;
00149 ++_writers;
00150 ResetEvent(_readEvent);
00151 ResetEvent(_writeEvent);
00152 ReleaseMutex(_mutex);
00153 poco_assert_dbg(_writers == 1);
00154 break;
00155 default:
00156 removeWriter();
00157 throw SystemException("cannot lock reader/writer lock");
00158 }
00159 }
00160
00161
00162 bool RWLockImpl::tryWriteLockImpl()
00163 {
00164 addWriter();
00165 HANDLE h[2];
00166 h[0] = _mutex;
00167 h[1] = _writeEvent;
00168 switch (WaitForMultipleObjects(2, h, TRUE, 1))
00169 {
00170 case WAIT_OBJECT_0:
00171 case WAIT_OBJECT_0 + 1:
00172 --_writersWaiting;
00173 ++_readers;
00174 ++_writers;
00175 ResetEvent(_readEvent);
00176 ResetEvent(_writeEvent);
00177 ReleaseMutex(_mutex);
00178 poco_assert_dbg(_writers == 1);
00179 return true;
00180 case WAIT_TIMEOUT:
00181 removeWriter();
00182 return false;
00183 default:
00184 removeWriter();
00185 throw SystemException("cannot lock reader/writer lock");
00186 }
00187 }
00188
00189
00190 void RWLockImpl::unlockImpl()
00191 {
00192 switch (WaitForSingleObject(_mutex, INFINITE))
00193 {
00194 case WAIT_OBJECT_0:
00195 _writers = 0;
00196 if (_writersWaiting == 0) SetEvent(_readEvent);
00197 if (--_readers == 0) SetEvent(_writeEvent);
00198 ReleaseMutex(_mutex);
00199 break;
00200 default:
00201 throw SystemException("cannot unlock reader/writer lock");
00202 }
00203 }
00204
00205
00206 }