// // semaphore.cpp // // Circle - A C++ bare metal environment for Raspberry Pi // Copyright (C) 2021-2026 R. Stange // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include #include #include CSemaphore::CSemaphore (unsigned nInitialCount) : m_nCount (nInitialCount), m_Event (m_nCount > 0) { assert (m_nCount >= 0); } CSemaphore::~CSemaphore (void) { assert (m_nCount >= 0); } unsigned CSemaphore::GetState (void) const { return AtomicGet (&m_nCount); } void CSemaphore::Down (void) { while (AtomicGet (&m_nCount) == 0) { m_Event.Wait (); } if (AtomicDecrement (&m_nCount) == 0) { assert (m_Event.GetState ()); m_Event.Clear (); } } boolean CSemaphore::DownWithTimeout (unsigned nMicroSeconds) { while (AtomicGet (&m_nCount) == 0) { if ( m_Event.WaitWithTimeout (nMicroSeconds) && !m_Event.GetState ()) { return TRUE; } } if (AtomicDecrement (&m_nCount) == 0) { assert (m_Event.GetState ()); m_Event.Clear (); } return FALSE; } void CSemaphore::Up (void) { if (AtomicIncrement (&m_nCount) == 1) { assert (!m_Event.GetState ()); m_Event.Set (); } #if NDEBUG else { assert (m_Event.GetState ()); } #endif } boolean CSemaphore::TryDown (void) { if (AtomicGet (&m_nCount) == 0) { return FALSE; } if (AtomicDecrement (&m_nCount) == 0) { assert (m_Event.GetState ()); m_Event.Clear (); } return TRUE; }