/* * Copyright (C) 2007-2023 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #include "bu/readwritemutex.h" Bu::ReadWriteMutex::ReadWriteMutex() : iCounter( 0 ), bWantWrite( false ) { } Bu::ReadWriteMutex::~ReadWriteMutex() { } void Bu::ReadWriteMutex::lockRead() { // Check to see if someone wants to write cWrite.lock(); if( bWantWrite ) { // If so, wait patiently for them to finish cWrite.wait(); } cWrite.unlock(); // Now lock the read counter mRead.lock(); iCounter++; // If the lock counter is one, we just locked for the first time, // so we lock the writer. if( iCounter == 1 ) mWrite.lock(); mRead.unlock(); } void Bu::ReadWriteMutex::unlockRead() { // Lock the read counter mRead.lock(); iCounter--; // If we just decremented the counter back to zero then we can // release the write lock if( iCounter == 0 ) mWrite.unlock(); mRead.unlock(); } // // The bWantWrite could be a counter like the read lock counter, however // once a write lock occurs and bWantWrite is set at least one write // will definately occur. In practice most writes all happen one after // the other anyway and this way reads get a chance to mingle in. // // Really, just getting all current reads to stop so a write can happen // I think is sufficient right now. // void Bu::ReadWriteMutex::lockWrite() { // Lock the read counter mRead.lock(); if( iCounter > 0 ) { // If there is an active read in progress then we set the bWantWrite // flag to make sure no more readers start working. cWrite.lock(); bWantWrite = true; cWrite.unlock(); } mRead.unlock(); // Lock the write lock mWrite.lock(); } void Bu::ReadWriteMutex::unlockWrite() { // Just always set the bWantWrite flag to false at this point, as long // as we're locked. cWrite.lock(); bWantWrite = false; cWrite.unlock(); // Release all waiting readers, they won't actually do much until we // unlock the write lock though cWrite.broadcast(); // Unlock the write lock mWrite.unlock(); }