/* PIP - Platform Independent Primitives PISemaphore, PISemaphoreLocker 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 . */ //! \addtogroup Thread //! \{ //! \class PISemaphore pisemaphore.h //! //! \~\brief //! \~english Basic semaphore //! \~russian Простой семафор //! //! //! \~\details //! \~english \section PISemaphore_sec0 Synopsis //! \~russian \section PISemaphore_sec0 Краткий обзор //! //! \~english //! %PISemaphore provides critical code section defence between several threads with resource counting. //! Semaphore contains logic counter and functions to change it: //! \a release(), \a acquire() and \a tryAcquire(). //! //! For automatic acquire-release use \a PISemaphoreLocker. //! //! \~russian //! %PISemaphore предоставляет межпотоковую защиту критических секций кода с подсчетом ресурсов. //! Семафор состоит из логического счетчика и методов для его изменения: //! \a release(), \a acquire() and \a tryAcquire(). //! //! Для автоматического захвата-освобождения используйте \a PISemaphoreLocker. //! //! \~english \section PISemaphore_sec1 Usage //! \~russian \section PISemaphore_sec1 Использование //! //! \~english //! //! \~russian //! //! \~\code //! \endcode //! \} //! \addtogroup Thread //! \{ //! \class PISemaphoreLocker pisemaphore.h //! //! \~\brief //! \~english %PISemaphore autolocker //! \~russian Автоблокировщик %PISemaphore //! //! //! \~\details //! //! \~english //! When a %PISemaphoreLocker object is created, it attempts to acquire the semaphore resources, if "condition" \c true. //! When control leaves the scope in which the %PISemaphoreLocker object was created, //! the %PISemaphoreLocker is destructed and the resources are released, if "condition" was \c true. //! //! If "condition" \c false this class do nothing. //! //! The %PISemaphoreLocker class is non-copyable. //! //! \~russian //! При создании экземпляра %PISemaphoreLocker захватываются ресурсы семафора, если "condition" \c true. //! Когда выполнение покидает область жизни объекта, вызывается его деструктор и ресурсы //! освобождаются, если "condition" был \c true. //! //! Если "condition" \c false, то этот объект ничего не делает. //! //! Класс %PISemaphoreLocker некопируемый. //! //! \~\code //! // critical section start //! { //! PISemaphoreLocker locker(mutex, 5); //! // ... your code here //! } //! // critical section end //! \endcode //! \} #include "pisemaphore.h" PISemaphore::PISemaphore(int initial) { count = initial; } PISemaphore::~PISemaphore() { var.notifyAll(); } void PISemaphore::acquire(int cnt) { PIMutexLocker _ml(mutex); while (count < cnt) { var.wait(mutex); } count -= cnt; } bool PISemaphore::tryAcquire(int cnt) { PIMutexLocker _ml(mutex); if (count < cnt) return false; count -= cnt; return true; } bool PISemaphore::tryAcquire(int cnt, PISystemTime timeout) { PITimeMeasurer tm; PIMutexLocker _ml(mutex); while (count < cnt) { PISystemTime remain = timeout - tm.elapsed(); if (remain.isNegative()) return false; var.waitFor(mutex, remain); } count -= cnt; return true; } void PISemaphore::release(int cnt) { PIMutexLocker _ml(mutex); count += cnt; var.notifyAll(); } int PISemaphore::available() const { PIMutexLocker _ml(mutex); return count; }