#pragma once #ifdef SIMULATE_FREESTANDING #define HAS_MUTEX 0 #else #define HAS_MUTEX __has_include() #endif #include #if HAS_MUTEX #include #endif #include #include namespace conc { namespace detail { template constexpr auto always_false_v = false; #if HAS_MUTEX template class standard_policy { template static inline Mutex m{}; public: template requires(sizeof...(Pred) < 2) static auto call_in_critical_section(F &&f, Pred &&...pred) -> decltype(std::forward(f)()) { while (true) { [[maybe_unused]] std::lock_guard l{m}; if ((... and pred())) { return std::forward(f)(); } } } }; #else template struct standard_policy { template requires(sizeof...(Pred) < 2) static auto call_in_critical_section(F &&f, Pred &&...) -> decltype(std::forward(f)()) { static_assert(always_false_v, "No standard concurrency policy defined: inject a policy " "by specializing conc::injected_policy<>"); return std::forward(f)(); } }; #endif } // namespace detail template inline auto injected_policy = detail::standard_policy{}; template requires(sizeof...(DummyArgs) == 0 and sizeof...(Pred) < 2) auto call_in_critical_section(F &&f, Pred &&...pred) -> decltype(std::forward(f)()) { policy auto &p = injected_policy; return p.template call_in_critical_section( std::forward(f), std::forward(pred)...); } } // namespace conc #undef HAS_MUTEX