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 #ifndef _terimber_keymaker_hpp_
00029 #define _terimber_keymaker_hpp_
00030
00031 #include "base/keymaker.h"
00032 #include "base/date.h"
00033
00034 BEGIN_TERIMBER_NAMESPACE
00035 #pragma pack(4)
00036
00037 inline
00038 keylocker::keylocker(size_t capacity) :
00039 _capacity(capacity),
00040 _opened(true),
00041 _clients(0),
00042 _ev_open(true, true),
00043 _ev_close(true, false),
00044 _ev_client(false, false),
00045 _ev_server(false, false)
00046 {
00047 }
00048
00049
00050 inline
00051 bool
00052 keylocker::enter(size_t timeout) const
00053 {
00054 size_t waittime = 0;
00055
00056 mutex_keeper guard(_access_mtx);
00057
00058 while (waittime < timeout)
00059 {
00060 if (!_opened)
00061 {
00062
00063 guard.unlock();
00064
00065
00066 date now;
00067
00068 if (WAIT_OBJECT_0 != _ev_open.wait(timeout - waittime))
00069 return false;
00070
00071
00072 guard.lock();
00073
00074
00075 waittime += (size_t)date::get_difference(now);
00076 }
00077 else if (_clients >= _capacity)
00078 {
00079
00080 guard.unlock();
00081
00082
00083 date now;
00084
00085 if (WAIT_OBJECT_0 != _ev_client.wait(timeout - waittime))
00086 return false;
00087
00088
00089 guard.lock();
00090
00091
00092 waittime += (size_t)date::get_difference(now);
00093 }
00094 else
00095 {
00096 ++_clients;
00097 return true;
00098 }
00099 }
00100
00101 return false;
00102 }
00103
00104 inline
00105 void
00106 keylocker::leave() const
00107 {
00108 mutex_keeper guard(_access_mtx);
00109
00110 assert(_clients > 0);
00111
00112 --_clients;
00113
00114 if (_opened)
00115 {
00116 guard.unlock();
00117 _ev_client.signal();
00118 }
00119 else if (!_clients)
00120 {
00121 guard.unlock();
00122 _ev_close.signal();
00123 }
00124 }
00125
00126
00127 inline
00128 bool
00129 keylocker::lock(size_t timeout) const
00130 {
00131 size_t waittime = 0;
00132
00133 mutex_keeper guard(_access_mtx);
00134
00135 while (waittime < timeout)
00136 {
00137 if (_opened)
00138 {
00139 _server_mtx.lock();
00140 _ev_open.nonsignal();
00141
00142 if (!_clients)
00143 {
00144 _opened = false;
00145
00146 _ev_close.nonsignal();
00147 return true;
00148 }
00149 }
00150
00151 if (!_opened)
00152 {
00153
00154 guard.unlock();
00155
00156
00157 date now;
00158
00159 if (WAIT_OBJECT_0 != _ev_server.wait(timeout - waittime))
00160 return false;
00161
00162
00163 guard.lock();
00164
00165
00166 waittime += (size_t)date::get_difference(now);
00167 }
00168 else if (_clients)
00169 {
00170 _opened = false;
00171
00172
00173
00174 guard.unlock();
00175
00176 if (WAIT_OBJECT_0 != _ev_close.wait(timeout - waittime))
00177 {
00178
00179 guard.lock();
00180
00181 _opened = true;
00182
00183
00184 guard.unlock();
00185
00186 _ev_open.signal();
00187
00188
00189 _server_mtx.unlock();
00190
00191 _ev_server.signal();
00192 return false;
00193 }
00194
00195
00196 _ev_close.nonsignal();
00197 return true;
00198 }
00199 }
00200
00201 return false;
00202 }
00203
00204 inline
00205 void
00206 keylocker::unlock() const
00207 {
00208
00209 mutex_keeper guard(_access_mtx);
00210
00211 if (_opened)
00212 {
00213 return;
00214 }
00215
00216 _opened = true;
00217
00218
00219 guard.unlock();
00220
00221 _ev_open.signal();
00222
00223
00224 _server_mtx.unlock();
00225
00226 _ev_server.signal();
00227 }
00228
00229 inline
00230 keylocker_server::keylocker_server(const keylocker& locker, size_t timeout) :
00231 _locker(locker)
00232 {
00233 _locked = _locker.lock(timeout);
00234 }
00235
00236
00237
00238 inline
00239 keylocker_server::~keylocker_server()
00240 {
00241 if (_locked)
00242 _locker.unlock();
00243 }
00244
00245
00246
00247 inline
00248 keylocker_server::operator bool() const
00249 {
00250 return _locked;
00251 }
00252
00253 inline
00254 bool
00255 keylocker_server::operator!() const
00256 {
00257 return !_locked;
00258 }
00259
00261 inline
00262 void
00263 keylocker_server::unlock() const
00264 {
00265 if (_locked)
00266 _locker.unlock(), _locked = false;
00267 }
00268
00270 inline
00271 void
00272 keylocker_server::lock(size_t timeout) const
00273 {
00274 if (!_locked)
00275 _locked = _locker.lock(timeout);
00276 }
00277
00279
00280
00281
00282
00283
00284 inline
00285 keylocker_client::keylocker_client(const keylocker& locker, size_t timeout) :
00286 _locker(locker)
00287 {
00288 _inside = _locker.enter(timeout);
00289 }
00290
00291
00292
00293 inline
00294 keylocker_client::~keylocker_client()
00295 {
00296 if (_inside)
00297 _locker.leave();
00298 }
00299
00300
00301 inline
00302 keylocker_client::operator bool() const
00303 {
00304 return _inside;
00305 }
00306
00307 inline
00308 bool
00309 keylocker_client::operator!() const
00310 {
00311 return !_inside;
00312 }
00313
00315 inline
00316 void
00317 keylocker_client::leave() const
00318 {
00319 if (_inside)
00320 _locker.leave(), _inside = false;
00321 }
00322
00324 inline
00325 void
00326 keylocker_client::enter(size_t timeout) const
00327 {
00328 if (!_inside)
00329 _inside = _locker.enter(timeout);
00330 }
00331
00332 #pragma pack()
00333 END_TERIMBER_NAMESPACE
00334
00335 #endif // _terimber_keymaker_hpp_
00336