#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2023 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library 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 IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_SUPPORT_THREADING_SEMAPHORE_H #define NUCLEX_SUPPORT_THREADING_SEMAPHORE_H #include "Nuclex/Support/Config.h" #include // for std::size_t #include // for std::chrono::microseconds namespace Nuclex { namespace Support { namespace Threading { // ------------------------------------------------------------------------------------------- // /// Lets only a specific number of threads enter at the same time /// /// /// This is a completely vanilla semaphore implementation that either delegates /// to the platform's threading library or uses available threading primitives to /// build the required behavior. /// /// /// Using it grants you automatic resource management, reduced header dependencies /// and guaranteed behavior, including actual relative timeouts on Posix platforms /// where the default implementation would use wall clock (meaning clock adjustment /// sensitive) timeouts. /// /// /// It's at least as fast as your platform's native semaphore, likely much faster. /// /// class NUCLEX_SUPPORT_TYPE Semaphore { /// Initializes a new semaphore with the specified initial count /// /// Initial number of threads that the semaphore will let through /// public: NUCLEX_SUPPORT_API Semaphore(std::size_t initialCount = 0); /// Frees all resources owned by the semaphore /// /// There should not be any threads waiting on the semaphore when it is destroyed. /// The behavior for such threats is undefined, they may hang forever, they /// may receive an exception or the entire process may be terminated. /// public: NUCLEX_SUPPORT_API ~Semaphore(); /// Increments the semaphore, letting one more thread through /// Number of times the semaphore will be incremented public: NUCLEX_SUPPORT_API void Post(std::size_t count = 1); /// /// Waits until the semaphore has a count above zero, then decrements the count /// /// /// This caues the calling thread to block if the semaphore didn't already have /// a positive count. If the thread is blocked, it will stay so until another /// thread calls on the semaphore. /// public: NUCLEX_SUPPORT_API void WaitThenDecrement(); /// /// Waits until the semaphore has a count above zero, then decrements the count /// /// How long to wait for the semaphore before giving up /// /// True if the semaphore let the thread through and was decremented, /// false if the timeout elapsed and the semaphore was not decremented. /// /// /// This causes the calling thread to block if the semaphore didn't already have /// a positive count. If the thread is blocked, it will stay so until another /// thread calls on the semaphore or until the specified /// patience time has elapsed. /// public: NUCLEX_SUPPORT_API bool WaitForThenDecrement( const std::chrono::microseconds &patience ); //public: void WaitUntilThenDecrement(const std::chrono::time_point< &patience); /// Structure to hold platform dependent process and file handles private: struct PlatformDependentImplementationData; /// Accesses the platform dependent implementation data container /// A reference to the platform dependent implementation data private: PlatformDependentImplementationData &getImplementationData(); #if defined(NUCLEX_SUPPORT_LINUX) || defined(NUCLEX_SUPPORT_WINDOWS) alignas(8) unsigned char implementationDataBuffer[sizeof(std::size_t) * 2]; #else // Posix unsigned char implementationDataBuffer[96]; #endif }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Support::Threading #endif // NUCLEX_SUPPORT_THREADING_SEMAPHORE_H