#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_GATE_H #define NUCLEX_SUPPORT_THREADING_GATE_H #include "Nuclex/Support/Config.h" #include // for std::uint32_t #include // for std::chrono::microseconds namespace Nuclex { namespace Support { namespace Threading { // ------------------------------------------------------------------------------------------- // /// Lets threads through only if opened /// /// /// This is one of the simplest thread synchronization primitives. It will /// simply block all threads while it is closed and let all threads through /// while it is open. /// /// /// It can be used in place of a reverse counting semaphore to wait for multiple /// threads to complete their work or to launch multiple threads if you /// intentionally want to construct a high-contention situation. /// /// /// To Windows and .NET developers, it is known as a "ManualResetEvent" /// /// class NUCLEX_SUPPORT_TYPE Gate { /// Initializes a new gate in an open or closed state /// Whether the gate is initially open public: NUCLEX_SUPPORT_API Gate(bool initiallyOpen = false); /// Frees all resources owned by the gate /// /// There should not be any threads waiting on the gate 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 ~Gate(); /// Opens the gate, letting any currently and future threads through public: NUCLEX_SUPPORT_API void Open(); /// Closes the gate, making any future threads wait in front of it public: NUCLEX_SUPPORT_API void Close(); /// Sets the state of the gate to opened or closed /// Whether the gate will be opened (true) or closed (false) public: NUCLEX_SUPPORT_API void Set(bool opened); /// /// Waits for the gate to open. Returns immediately if it already is open. /// public: NUCLEX_SUPPORT_API void Wait() const; /// /// Waits for the gate to open. Returns immediately if it already is open. /// /// /// How long to wait for the gate to open before giving up /// /// True if the gate was opened, false if the patience time has elapsed public: NUCLEX_SUPPORT_API bool WaitFor(const std::chrono::microseconds &patience) const; //public: void WaitUntil(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: const PlatformDependentImplementationData &getImplementationData() const; /// Accesses the platform dependent implementation data container /// A reference to the platform dependent implementation data private: PlatformDependentImplementationData &getImplementationData(); private: union alignas(8) { /// Platform dependent process and file handles used for the process PlatformDependentImplementationData *implementationData; /// Used to hold the platform dependent implementation data if it fits /// /// Small performance / memory fragmentation improvement. /// This avoids a micro-allocation for the implenmentation data structure in most cases. /// #if defined(NUCLEX_SUPPORT_LINUX) || defined(NUCLEX_SUPPORT_WINDOWS) alignas(8) unsigned char implementationDataBuffer[sizeof(std::uint32_t)]; #else // Posix unsigned char implementationDataBuffer[96]; #endif }; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Support::Threading #endif // NUCLEX_SUPPORT_THREADING_SEMAPHORE_H