00001
00014 #include <dlrThread/exception.h>
00015 #include <dlrThread/monitor.h>
00016 #include <dlrThread/private.h>
00017
00018
00019 namespace dlr {
00020
00021 namespace thread {
00022
00023
00024 Token::
00025 Token()
00026 : m_isTimed(false),
00027 m_lockPtr(0),
00028 m_timedLockPtr(0),
00029 m_referenceCount(0)
00030 {
00031
00032 }
00033
00034
00035 Token::
00036 Token(const Token& other)
00037 : m_isTimed(other.m_isTimed),
00038 m_lockPtr(other.m_lockPtr),
00039 m_timedLockPtr(other.m_timedLockPtr),
00040 m_referenceCount(other.m_referenceCount)
00041 {
00042
00043 }
00044
00045
00046 Token&
00047 Token::
00048 operator=(const Token& other)
00049 {
00050 if(this != &other) {
00051 m_isTimed = other.m_isTimed;
00052 m_lockPtr = other.m_lockPtr;
00053 m_timedLockPtr = other.m_timedLockPtr;
00054 m_referenceCount = other.m_referenceCount;
00055 }
00056 return *this;
00057 }
00058
00059
00060 Token::
00061 Token(boost::timed_mutex& mutex)
00062 : m_isTimed(false),
00063 m_lockPtr(new boost::timed_mutex::scoped_lock(mutex)),
00064 m_timedLockPtr(0),
00065 m_referenceCount()
00066 {
00067
00068 }
00069
00070
00071 Token::
00072 Token(boost::timed_mutex& mutex, double timeout)
00073 : m_isTimed(true),
00074 m_lockPtr(0),
00075 m_timedLockPtr(0),
00076 m_referenceCount()
00077 {
00078 if(timeout < 0.0) {
00079 timeout = 0.0;
00080 }
00081 boost::xtime xtimeout;
00082 if(!getXTime(timeout, xtimeout)) {
00083 DLR_THROW(RunTimeException, "Token::Token()",
00084 "Can't get current time.");
00085 }
00086 try {
00087 m_timedLockPtr =
00088 new boost::timed_mutex::scoped_timed_lock(mutex, xtimeout);
00089 } catch(boost::lock_error&) {
00090
00091 }
00092 }
00093
00094
00095 Token::
00096 ~Token() {
00097 if (!m_referenceCount.isShared()) {
00098 if(m_isTimed) {
00099 delete m_timedLockPtr;
00100 } else {
00101 delete m_lockPtr;
00102 }
00103 }
00104 }
00105
00106
00107 Token::
00108 operator bool()
00109 {
00110 return ((m_lockPtr != 0) || (m_timedLockPtr != 0));
00111 }
00112
00113
00114 boost::timed_mutex::scoped_lock&
00115 Token::
00116 getLock()
00117 {
00118 return *m_lockPtr;
00119 }
00120
00121
00122 boost::timed_mutex::scoped_timed_lock&
00123 Token::
00124 getTimedLock()
00125 {
00126 return *m_timedLockPtr;
00127 }
00128
00129
00130 bool
00131 Token::
00132 isTimed()
00133 {
00134 return m_isTimed;
00135 }
00136
00137
00138 Condition::
00139 Condition(boost::condition* conditionPtr)
00140 : m_conditionPtr(conditionPtr)
00141 {
00142
00143 }
00144
00145
00146 Condition::
00147 Condition(const Condition& other)
00148 : m_conditionPtr(other.m_conditionPtr)
00149 {
00150
00151 }
00152
00153
00154 Condition::
00155 ~Condition()
00156 {
00157
00158 }
00159
00160
00161 Condition&
00162 Condition::
00163 operator=(const Condition& other)
00164 {
00165 if(&other != this) {
00166 m_conditionPtr = other.m_conditionPtr;
00167 }
00168 return *this;
00169 }
00170
00171
00172 void
00173 Condition::
00174 signalOne()
00175 {
00176 if(m_conditionPtr != 0) {
00177 m_conditionPtr->notify_one();
00178 }
00179 }
00180
00181
00182 void
00183 Condition::
00184 signalAll()
00185 {
00186 if(m_conditionPtr != 0) {
00187 m_conditionPtr->notify_all();
00188 }
00189 }
00190
00191
00192 void
00193 Condition::
00194 wait(Token& token)
00195 {
00196 if(m_conditionPtr != 0) {
00197 if(token.isTimed()) {
00198 m_conditionPtr->wait(token.getTimedLock());
00199 } else {
00200 m_conditionPtr->wait(token.getLock());
00201 }
00202 }
00203 }
00204
00205
00206 bool
00207 Condition::
00208 wait(Token& token, double timeout)
00209 {
00210 if(m_conditionPtr != 0) {
00211 if(timeout < 0.0) {
00212 timeout = 0.0;
00213 }
00214 boost::xtime xtimeout;
00215 if(!getXTime(timeout, xtimeout)) {
00216 return false;
00217 }
00218 if(token.isTimed()) {
00219 return m_conditionPtr->timed_wait(token.getTimedLock(), xtimeout);
00220 }
00221 return m_conditionPtr->timed_wait(token.getLock(), xtimeout);
00222 }
00223 return false;
00224 }
00225
00226
00227
00228 Monitor::
00229 Monitor()
00230 : m_tokenMutexPtr(new boost::timed_mutex),
00231 m_boostConditionVectorPtr(new std::vector<boost::condition*>),
00232 m_isCopyable(false),
00233 m_referenceCountPtr(new size_t)
00234 {
00235 *m_referenceCountPtr = 1;
00236 }
00237
00238
00239
00240 Monitor::
00241 Monitor(const Monitor& other)
00242 : m_tokenMutexPtr(0),
00243 m_boostConditionVectorPtr(0),
00244 m_isCopyable(false),
00245 m_referenceCountPtr(0)
00246 {
00247 this->copyOther(other);
00248 }
00249
00250
00251
00252 Monitor::
00253 ~Monitor()
00254 {
00255 this->releaseResources();
00256 }
00257
00258
00259
00260 Monitor&
00261 Monitor::
00262 operator=(const Monitor& other)
00263 {
00264 if(&other != this) {
00265 if(!m_isCopyable) {
00266 DLR_THROW(LogicException, "Monitor::operator=()",
00267 "Attempt to copy a Monitor instance or subclass "
00268 "without explicitly enabling copying.");
00269 }
00270 this->releaseResources();
00271 this->copyOther(other);
00272 }
00273 return *this;
00274 }
00275
00276
00277
00278
00279
00280 void
00281 Monitor::
00282 copyOther(const Monitor& other)
00283 {
00284
00285
00286 m_tokenMutexPtr = other.m_tokenMutexPtr;
00287 {
00288 Token token = this->getToken();
00289 if(!other.m_isCopyable) {
00290 DLR_THROW(LogicException, "Monitor::copyOther()",
00291 "Attempt to copy a Monitor instance or subclass "
00292 "without explicitly enabling copying.");
00293 }
00294 m_boostConditionVectorPtr = other.m_boostConditionVectorPtr;
00295 m_isCopyable = other.m_isCopyable;
00296 m_referenceCountPtr = other.m_referenceCountPtr;
00297 ++(*m_referenceCountPtr);
00298 }
00299 }
00300
00301
00302
00303
00304 Condition
00305 Monitor::
00306 createCondition(bool doInitialize)
00307 {
00308 if(doInitialize) {
00309
00310
00311
00312 Token token = this->getToken();
00313 m_boostConditionVectorPtr->push_back(new boost::condition);
00314 size_t index0 = m_boostConditionVectorPtr->size() - 1;
00315 return Condition((*m_boostConditionVectorPtr)[index0]);
00316 }
00317 return Condition(0);
00318 }
00319
00320
00321
00322
00323 void
00324 Monitor::
00325 releaseResources()
00326 {
00327 bool isShared = true;
00328 {
00329 Token token = this->getToken();
00330 if(--(*m_referenceCountPtr) == 0) {
00331 isShared = false;
00332 }
00333 }
00334
00335 if(!isShared) {
00336
00337
00338 for(size_t index0 = 0; index0 < m_boostConditionVectorPtr->size();
00339 ++index0) {
00340 delete (*m_boostConditionVectorPtr)[index0];
00341 }
00342
00343 delete m_tokenMutexPtr;
00344 m_tokenMutexPtr = 0;
00345 delete m_boostConditionVectorPtr;
00346 m_boostConditionVectorPtr = 0;
00347 delete m_referenceCountPtr;
00348 m_referenceCountPtr = 0;
00349 }
00350 }
00351
00352 }
00353
00354 }