AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
AAsyncHolder.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include "AFuture.h"
15#include <any>
16#include <list>
17
18
31public:
32 AAsyncHolder() = default;
34 std::unique_lock lock(mSync);
35
36 while (!mFutureSet.empty()) {
37 auto l = std::move(mFutureSet.last());
38 mFutureSet.pop_back();
39 lock.unlock();
40 l.cancel();
41 l.wait();
42 l = nullptr;
43 lock.lock();
44 }
45
46 while (!mCustomTypeFutures.empty()) {
47 auto l = std::move(mCustomTypeFutures.back());
48 mCustomTypeFutures.pop_back();
49 lock.unlock();
50 l->cancelAndWait();
51 l = nullptr;
52 lock.lock();
53 }
54 mDead = true;
55 }
56
57 template<typename T>
58 AAsyncHolder& operator<<(AFuture<T> future) {
59 std::unique_lock lock(mSync);
60 if constexpr (std::is_same_v<void, T>) {
61 auto impl = future.inner().get();
62 mFutureSet << future;
63 lock.unlock();
64 future.onSuccess([this, impl]() {
65 std::unique_lock lock(mSync);
66 mFutureSet.removeIf([&](const AFuture<>& f) {
67 return f.inner().get() == impl;
68 });
69 });
70 } else {
71 auto uniquePtr = std::make_unique<Future<T>>(future);
72 auto it = mCustomTypeFutures.insert(mCustomTypeFutures.end(), std::move(uniquePtr));
73
74 lock.unlock();
75
76 future.onSuccess([this, it](const T& result) {
77 AUI_ASSERTX(!mDead, "you have concurrency issues");
78 std::unique_lock lock(mSync);
79 AUI_ASSERT(!mCustomTypeFutures.empty());
80 mCustomTypeFutures.erase(it);
81 });
82 }
83 return *this;
84 }
85
86 [[nodiscard]]
87 std::size_t size() const {
88 std::unique_lock lock(mSync);
89 return mFutureSet.size();
90 }
91
92 void waitForAll() {
93 std::unique_lock lock(mSync);
94 if (!mFutureSet.empty()) {
95 waitAgain:
96 auto futureSet = std::move(mFutureSet);
97 lock.unlock();
98 futureSet.waitForAll();
99 lock.lock();
100 if (mFutureSet.empty()) {
101 mFutureSet = std::move(futureSet);
102 } else {
103 mFutureSet.insertAll(futureSet);
104 goto waitAgain;
105 }
106 }
107
108 while (!mCustomTypeFutures.empty()) {
109 mCustomTypeFutures.front()->wait(lock);
110 }
111 }
112
113private:
114 struct IFuture {
115 virtual ~IFuture() = default;
116 virtual void get() = 0;
117 virtual void wait(std::unique_lock<AMutex>& lock) = 0;
118 virtual void cancelAndWait() = 0;
119 };
120 bool mDead = false;
121
122 template<typename T>
123 struct Future: IFuture {
124 void get() override {
125 mFuture.cancel();
126 *mFuture;
127 }
128 void wait(std::unique_lock<AMutex>& lock) override {
129 auto copy = mFuture;
130 lock.unlock();
131 copy.wait();
132 lock.lock();
133 }
134
135 void cancelAndWait() override {
136 mFuture.cancel();
137 mFuture.wait();
138 }
139
140 ~Future() override = default;
141
142 Future(AFuture<T> future) : mFuture(std::move(future)) {}
143
144 private:
145 AFuture<T> mFuture;
146 };
147
148
149 mutable AMutex mSync;
150 AFutureSet<> mFutureSet;
151 std::list<_unique<IFuture>> mCustomTypeFutures;
152};
Holds a set of futures keeping them valid.
Definition: AAsyncHolder.h:30
Manages multiple futures.
Definition: AThreadPool.h:175
Represents a value that will be available at some point in the future.
Definition: AFuture.h:620
const AFuture & onSuccess(Callback &&callback) const noexcept
Add onSuccess callback to the future.
Definition: AFuture.h:698
void removeIf(Predicate &&predicate) noexcept
Definition: AVector.h:333
StoredType & last() noexcept
Definition: AVector.h:256
iterator insertAll(const OtherContainer &c) noexcept
Definition: AVector.h:60
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition: Assert.h:55
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition: Assert.h:74
Basic syscall-based synchronization primitive.
Definition: AMutex.h:33