Files
pip/libs/main/thread/pireadwritelock.cpp

235 lines
7.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
PIP - Platform Independent Primitives
PIReadWriteLock, PIReadLocker, PIWriteLocker
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \addtogroup Thread
//! \{
//! \class PIReadWriteLock pireadwritelock.h
//!
//! \~\brief
//! \~english Read/Write lock
//! \~russian Блокировка чтения/записи
//!
//!
//! \~\details
//! \~english \section PIReadWriteLock_sec0 Synopsis
//! \~russian \section PIReadWriteLock_sec0 Краткий обзор
//!
//! \~english
//! %PIReadWriteLock provides more complex critical code section defence between several threads.
//! %PIReadWriteLock permit only one thread to modify data, besides multiple thread can read data
//! simultaneously. Conatains methods:
//! \a lockWrite(), \a tryLockWrite(), \a unlockWrite(), \a lockRead(), \a tryLockRead() and \a unlockRead().
//!
//! For automatic read and write locks use \a PIReadLocker and \a PIWriteLocker.
//!
//! \~russian
//! %PIReadWriteLock предоставляет более сложную межпотоковую защиту критических секций кода.
//! %PIReadWriteLock разрешает только одному потоку изменять данные, в то время как читать данные
//! могут одновременно несколько потоков.
//! Содержит методы:
//! \a lockWrite(), \a tryLockWrite(), \a unlockWrite(), \a lockRead(), \a tryLockRead() и \a unlockRead().
//!
//! Для автоматической блокировки на чтение и запись используйте \a PIReadLocker и \a PIWriteLocker.
//!
//! \~english \section PIReadWriteLock_sec1 Usage
//! \~russian \section PIReadWriteLock_sec1 Использование
//!
//! \~english
//! When one thread lock for write with \a lockWrite(), all other threads (read and write) can`t access data until this thread
//! call \a unlockWrite(). In this way, write lock works similar to mutex.
//!
//! On the other hand, several threads can simultaneously read data. In other words, \a lockRead() increase read threads counter
//! and \a unlockRead() decrease. But thread can`t read data while other thread locked for write.
//!
//! \~russian
//! Когда один поток блокирует запись с помощью функции \a lockWrite(), все остальные потоки (чтение и запись) не смогут получить
//! доступ к данным, пока этот поток не вызовет \a unlockWrite(). Таким образом, блокировка записи работает аналогично мьютексу.
//!
//! С другой стороны, несколько потоков могут одновременно считывать данные. Другими словами, функция \a lockRead() увеличивает счетчик
//! потоков чтения, а функция \a unlockRead() уменьшает. Но поток не может считывать данные, пока другой поток заблокирован для записи.
//!
//! \~\code
//! \endcode
//! \}
//! \addtogroup Thread
//! \{
//! \class PIReadLocker pireadwritelock.h
//!
//! \~\brief
//! \~english %PIReadWriteLock read autolocker
//! \~russian Автоблокировщик на чтение %PIReadWriteLock
//!
//!
//! \~\details
//!
//! \~english
//! When a %PIReadLocker object is created, it lock %PIReadWriteLock for read, if "condition" \c true.
//! When control leaves the scope in which the %PIReadLocker object was created,
//! the %PIReadLocker is destructed and unlock for read, if "condition" was \c true.
//!
//! If "condition" \c false this class do nothing.
//!
//! The %PIReadLocker class is non-copyable.
//!
//! \~russian
//! При создании экземпляра %PIReadLocker он блокирует %PIReadWriteLock на чтение, если "condition" \c true.
//! Когда выполнение покидает область жизни объекта, вызывается его деструктор и освобождается блокировка на чтение,
//! если "condition" был \c true.
//!
//! Если "condition" \c false, то этот объект ничего не делает.
//!
//! Класс %PIReadLocker некопируемый.
//!
//! \~\code
//! // critical section start
//! {
//! PIReadLocker locker(rw_lock);
//! // ... your read code here
//! }
//! // critical section end
//! \endcode
//! \}
//! \addtogroup Thread
//! \{
//! \class PIWriteLocker pireadwritelock.h
//!
//! \~\brief
//! \~english %PIReadWriteLock write autolocker
//! \~russian Автоблокировщик на запись %PIReadWriteLock
//!
//!
//! \~\details
//!
//! \~english
//! When a %PIWriteLocker object is created, it lock %PIReadWriteLock for write, if "condition" \c true.
//! When control leaves the scope in which the %PIWriteLocker object was created,
//! the %PIWriteLocker is destructed and unlock for write, if "condition" was \c true.
//!
//! If "condition" \c false this class do nothing.
//!
//! The %PIWriteLocker class is non-copyable.
//!
//! \~russian
//! При создании экземпляра %PIWriteLocker он блокирует %PIReadWriteLock на запись, если "condition" \c true.
//! Когда выполнение покидает область жизни объекта, вызывается его деструктор и освобождается блокировка на запись,
//! если "condition" был \c true.
//!
//! Если "condition" \c false, то этот объект ничего не делает.
//!
//! Класс %PIWriteLocker некопируемый.
//!
//! \~\code
//! // critical section start
//! {
//! PIWriteLocker locker(rw_lock);
//! // ... your write code here
//! }
//! // critical section end
//! \endcode
//! \}
#include "pireadwritelock.h"
PIReadWriteLock::PIReadWriteLock() {}
PIReadWriteLock::~PIReadWriteLock() {
var.notifyAll();
}
void PIReadWriteLock::lockWrite() {
PIMutexLocker _ml(mutex);
while (reading > 0 || writing) {
var.wait(mutex);
}
writing = true;
}
bool PIReadWriteLock::tryLockWrite() {
PIMutexLocker _ml(mutex);
if (reading > 0 || writing) return false;
writing = true;
return true;
}
bool PIReadWriteLock::tryLockWrite(PISystemTime timeout) {
PITimeMeasurer tm;
PIMutexLocker _ml(mutex);
while (reading > 0 || writing) {
PISystemTime remain = timeout - tm.elapsed();
if (remain.isNegative()) return false;
var.waitFor(mutex, remain);
}
writing = true;
return true;
}
void PIReadWriteLock::unlockWrite() {
PIMutexLocker _ml(mutex);
writing = false;
var.notifyAll();
}
void PIReadWriteLock::lockRead() {
PIMutexLocker _ml(mutex);
while (writing) {
var.wait(mutex);
}
++reading;
}
bool PIReadWriteLock::tryLockRead() {
PIMutexLocker _ml(mutex);
if (writing) return false;
++reading;
return true;
}
bool PIReadWriteLock::tryLockRead(PISystemTime timeout) {
PITimeMeasurer tm;
PIMutexLocker _ml(mutex);
while (writing) {
PISystemTime remain = timeout - tm.elapsed();
if (remain.isNegative()) return false;
var.waitFor(mutex, remain);
}
++reading;
return true;
}
void PIReadWriteLock::unlockRead() {
PIMutexLocker _ml(mutex);
--reading;
var.notifyAll();
}