/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2018 Danny Robson */ #include "semaphore_win32.hpp" #include "../debug.hpp" using cruft::thread::semaphore; /////////////////////////////////////////////////////////////////////////////// semaphore::semaphore (): semaphore (1) { ; } //----------------------------------------------------------------------------- semaphore::semaphore (int initial): m_value (initial) { ; } /////////////////////////////////////////////////////////////////////////////// int semaphore::acquire (int count) { CHECK_GE (count, 0); do { int now = m_value; // if our value is positive then attempt to decrement it and return, // else retry because someone interfered with us. if (now - count >= 0) { if (m_value.compare_exchange_weak (now, now - count)) return now - count; continue; } // the count doesn't appear to allow us to acquire. sleep until // there's been a modification and retry. std::unique_lock lk (m_mutex); m_cv.wait (lk, [&, this] () { return m_value - count >= 0; }); } while (1); } //----------------------------------------------------------------------------- int semaphore::acquire (void) { return acquire (1); } //----------------------------------------------------------------------------- int semaphore::release (int count) { auto res = m_value += count; if (res > 0) m_cv.notify_one(); return res; } //----------------------------------------------------------------------------- int semaphore::release (void) { return release (1); } /////////////////////////////////////////////////////////////////////////////// int semaphore::value (void) const { return m_value; } //----------------------------------------------------------------------------- int semaphore::operator++ (void) { return release (); } //----------------------------------------------------------------------------- int semaphore::operator-- (void) { // we don't need to wake anyone because this will only serve to delay // their wakeup. return --m_value; }