6 #ifndef LLU_ASYNC_UTILITIES_H
7 #define LLU_ASYNC_UTILITIES_H
15 namespace LLU::Async {
24 struct TypeErasedCallableBase {
25 virtual void call() = 0;
26 virtual ~TypeErasedCallableBase() =
default;
34 struct TypeErasedCallable : TypeErasedCallableBase {
35 explicit TypeErasedCallable(F&& f) : callable(std::forward<F>(f)) {}
37 void call()
override {
49 template<
typename F,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv<F>, FunctionWrapper>>>
50 explicit FunctionWrapper(F&& f) : impl {std::make_unique<TypeErasedCallable<F>>(std::forward<F>(f))} {}
59 template<
typename F,
typename... Args>
61 auto boundF = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
62 impl = std::make_unique<TypeErasedCallable<F>>(std::move(boundF));
81 std::unique_ptr<TypeErasedCallableBase> impl =
nullptr;
92 std::vector<std::thread>& threads;
99 explicit ThreadJoiner(std::vector<std::thread>& threadsToJoin) : threads(threadsToJoin) {}
108 for (
auto& t : threads) {
124 template<
typename FunctionType,
typename... Args>
125 std::packaged_task<std::invoke_result_t<FunctionType, Args...>()>
getPackagedTask(FunctionType&& f, Args&&... args) {
126 using result_type = std::invoke_result_t<FunctionType, Args...>;
128 auto boundF = std::bind(std::forward<FunctionType>(f), std::forward<Args>(args)...);
129 return std::packaged_task<result_type()> {std::move(boundF)};
137 std::atomic_bool pausedQ =
false;
138 std::mutex workersMutex;
139 std::condition_variable pausedWorkers;
146 std::unique_lock lck {workersMutex};
147 pausedWorkers.wait(lck, [&]() ->
bool {
return !pausedQ; });
159 pausedWorkers.notify_all();
164 #endif // LLU_ASYNC_UTILITIES_H