📄 readwritesem.cpp
字号:
int milliseconds){//-----------------------------------------------------------------// Lock this object to maintain integrity while we decide// exactly what to do next.//----------------------------------------------------------------- // AutoPtr<IPCException> caught; // IPCException caught((ThreadType)0); // WaitFailed caughtWaitFailed((ThreadType)0); // TimeOut caughtTimeOut((ThreadType)0); // TooManyReaders caughtTooManyReaders((ThreadType)0); ThreadType zero; IPCException caught(zero); WaitFailed caughtWaitFailed(zero); TimeOut caughtTimeOut(zero); TooManyReaders caughtTooManyReaders(zero); // cleanup stack frame { // Threads::cleanup_push(extricate_read_write, this); try { if (milliseconds == 0) _rwlock._internal_lock.try_lock(); else if (milliseconds == -1) _rwlock._internal_lock.lock(); else _rwlock._internal_lock.timed_lock(milliseconds); } catch (const IPCException & e) { caught = e; goto throw_from_here; } if (mode == PEG_SEM_WRITE) {//-----------------------------------------------------------------// Write Lock Step 1: lock the object and allow all the readers to exit//----------------------------------------------------------------- if (milliseconds == 0) // fast wait { if (_readers.get() > 0) { _rwlock._internal_lock.unlock(); // caught.reset(new WaitFailed(Threads::self())); caughtWaitFailed = WaitFailed(Threads::self()); goto throw_from_here; } } else if (milliseconds == -1) // infinite wait { while (_readers.get() > 0) Threads::yield(); } else // timed wait { struct timeval start, now; Time::gettimeofday(&start); start.tv_usec += (1000 * milliseconds); while (_readers.get() > 0) { Time::gettimeofday(&now); if ((now.tv_usec > start.tv_usec) || now.tv_sec > start.tv_sec) { _rwlock._internal_lock.unlock(); // caught.reset(new TimeOut(Threads::self())); caughtTimeOut = TimeOut(Threads::self()); goto throw_from_here; } Threads::yield(); } }//-----------------------------------------------------------------// Write Lock Step 2: Obtain the Write Mutex// Although there are no readers, there may be a writer//----------------------------------------------------------------- if (milliseconds == 0) // fast wait { try { _rwlock._wlock.try_lock(); } catch (IPCException & e) { _rwlock._internal_lock.unlock(); caught = e; goto throw_from_here; } } else if (milliseconds == -1) // infinite wait { try { _rwlock._wlock.lock(); } catch (const IPCException & e) { _rwlock._internal_lock.unlock(); caught = e; goto throw_from_here; } } else // timed wait { try { _rwlock._wlock.timed_lock(milliseconds); } catch (const IPCException & e) { _rwlock._internal_lock.unlock(); caught = e; goto throw_from_here; } }//-----------------------------------------------------------------// Write Lock Step 3: set the writer count to one, unlock the object// There are no readers and we are the only writer !//----------------------------------------------------------------- _writers = 1; // set the owner _rwlock._owner = Threads::self(); // unlock the object _rwlock._internal_lock.unlock(); } // PEG_SEM_WRITE else {//-----------------------------------------------------------------// Read Lock Step 1: Wait for the existing writer (if any) to clear//----------------------------------------------------------------- if (milliseconds == 0) // fast wait { if (_writers.get() > 0) { _rwlock._internal_lock.unlock(); // caught.reset(new WaitFailed(Threads::self())); caughtWaitFailed = WaitFailed(Threads::self()); goto throw_from_here; } } else if (milliseconds == -1) // infinite wait { while (_writers.get() > 0) Threads::yield(); } else // timed wait { struct timeval start, now; Time::gettimeofday(&start); start.tv_usec += (milliseconds * 1000); while (_writers.get() > 0) { Time::gettimeofday(&now); if ((now.tv_usec > start.tv_usec) || (now.tv_sec > start.tv_sec)) { _rwlock._internal_lock.unlock(); // caught.reset(new TimeOut(Threads::self())); caughtTimeOut = TimeOut(Threads::self()); goto throw_from_here; } Threads::yield(); Time::gettimeofday(&now); } }//-----------------------------------------------------------------// Read Lock Step 2: wait for a reader slot to open up, then return// At this point there are no writers, but there may be too many// readers.//----------------------------------------------------------------- if (milliseconds == 0) // fast wait { try { _rwlock._rlock.try_wait(); } catch (const IPCException &) { // the wait failed, there must be too many readers // already. // unlock the object caughtTooManyReaders = TooManyReaders(Threads::self()); _rwlock._internal_lock.unlock(); // caught.reset(new TooManyReaders(Threads::self())); } } else if (milliseconds == -1) // infinite wait { try { _rwlock._rlock.wait(); } catch (const IPCException & e) { _rwlock._internal_lock.unlock(); caught = e; goto throw_from_here; } } else // timed wait { try { _rwlock._rlock.time_wait(milliseconds); } catch (const IPCException & e) { _rwlock._internal_lock.unlock(); caught = e; goto throw_from_here; } }//-----------------------------------------------------------------// Read Lock Step 3: increment the number of readers, unlock the object,// return//----------------------------------------------------------------- _readers++; _rwlock._internal_lock.unlock(); } throw_from_here: // ATTN: Threads::cleanup_pop(0); } if (!Threads::null(caught.get_owner())) throw caught; if (!Threads::null(caughtWaitFailed.get_owner())) throw caughtWaitFailed; if (!Threads::null(caughtTimeOut.get_owner())) throw caughtTimeOut; if (!Threads::null(caughtTooManyReaders.get_owner())) throw caughtTooManyReaders; return;}//---------------------------------------------------------------------void ReadWriteSem::wait(Uint32 mode, ThreadType caller){ timed_wait(mode, caller, -1);}void ReadWriteSem::try_wait(Uint32 mode, ThreadType caller){ timed_wait(mode, caller, 0);}void ReadWriteSem::unlock(Uint32 mode, ThreadType caller){ if (mode == PEG_SEM_WRITE && _writers.get() != 0) { _writers = 0; _rwlock._wlock.unlock(); } else if (_readers.get() != 0) { _readers--; _rwlock._rlock.signal(); }}int ReadWriteSem::read_count() const{ return _readers.get();}int ReadWriteSem::write_count() const{ return _writers.get();}#endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */PEGASUS_NAMESPACE_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -