void RWLock_local::read_lock() { mutex.lock(); #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif if (state.writerswaiting > 0 || state.writing > 0) { state.readerswaiting++; #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif while (state.writerswaiting > 0 || state.writing > 0) okToRead.wait(mutex); state.readerswaiting--; } state.reading++; #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif mutex.unlock(); }
void RWLock_local::upgrade_to_write() { mutex.lock(); #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif state.reading--; // try to cut in line if (state.reading == 0) { state.writing++; #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif return; } // cut & paste from write_lock() if (state.writing > 0 || state.reading > 0) { state.writerswaiting++; #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif while (state.writing > 0 || state.reading > 0) okToWrite.wait(mutex); state.writerswaiting--; } state.writing++; }
void RWLock_local::read_unlock() { mutex.lock(); #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif state.reading--; if (state.writerswaiting > 0 && state.reading == 0) okToWrite.notify_one(); #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif mutex.unlock(); }
/* It's safe (and necessary) to simply convert this writer to a reader without blocking */ void RWLock_local::downgrade_to_read() { #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif state.writing--; if (state.readerswaiting > 0) okToRead.notify_all(); state.reading++; #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif mutex.unlock(); }
void RWLock_local::write_unlock() { #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif state.writing--; if (state.writerswaiting > 0) okToWrite.notify_one(); else if (state.readerswaiting > 0) okToRead.notify_all(); #ifdef DEBUG CHECKSAFETY(); CHECKLIVENESS(); #endif mutex.unlock(); }