MT Core (C++)
Core library for replacing C++ standard in project usage
Loading...
Searching...
No Matches
future.hpp
Go to the documentation of this file.
1/*
2
3Copyright 2025 Matthew Tolman
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17*/
18
19#ifndef MTCORE_MTTHREAD_FUTURE_HPP
20#define MTCORE_MTTHREAD_FUTURE_HPP
21
22#include "mtcore_thread/arc.hpp"
24#include <condition_variable>
25#include <functional>
26#include <mutex>
27
28namespace mtcore::thread {
29 template<typename T, typename E = void>
30 struct FutureState;
31
49 template<typename T, typename E = void>
50 struct Future {
52
58 auto res = state.acquire(alloc);
59 if (res.is_error()) {
60 return res.error();
61 }
62 return Future{.state = res.value()};
63 }
64
68 [[nodiscard]] T wait() { return state->wait(); }
69
74 void deinit(Allocator &alloc) { state.deinit(alloc); }
75 };
76
86 template<typename T>
87 struct FutureState<T, void> {
88 std::mutex mux = {};
89 std::condition_variable cv = {};
91
93 void set_val(const T &v) {
94 auto l = std::unique_lock{mux};
95 ensure(value.empty(), "CANNOT SET FUTURE VALUE MULTIPLE TIMES! CONSIDER USING A CANNEL OR INBOX!");
96 value = v;
97 cv.notify_all();
98 }
99
101 T wait() {
102 auto l = std::unique_lock{mux};
103 while (value.empty()) {
104 cv.wait(l);
105 }
106 return *value;
107 }
108
113
119 Arc<FutureState> state;
120 if (auto err = state.init(alloc); err.is_error()) {
121 return err.error();
122 }
123 auto futureArc = state.acquire(alloc);
124 if (futureArc.is_error()) {
125 state.deinit(alloc);
127 }
128 return make_res{.future = Future<T>{.state = futureArc.value()}, .state = state};
129 }
130 };
131
140 template<typename T, typename E>
141 struct FutureState {
142 std::mutex mux = {};
143 std::condition_variable cv = {};
146
147 void set_val(const T &v) {
148 auto l = std::unique_lock{mux};
149 ensure(value.empty(), "CANNOT SET FUTURE VALUE MULTIPLE TIMES! CONSIDER USING A "
150 "CANNEL OR INBOX!");
151 value = v;
152 cv.notify_all();
153 }
154
156 T wait() {
157 auto l = std::unique_lock{mux};
158 while (value.empty()) {
159 cv.wait(l);
160 }
161 return *value;
162 }
163
164 void deinit(Allocator &alloc) {
165 if (extra) {
166 extra.deinit(alloc);
167 }
168 }
169
174
183 std::function<Result<Arc<E>, AllocationError>(Allocator &alloc, Arc<FutureState> &)> getExtra) {
184 Arc<FutureState> state;
185 if (auto err = state.init(alloc); err.is_error()) {
186 return err.error();
187 }
188 Result<Arc<E>, AllocationError> extra = getExtra(alloc, state);
189 if (extra.is_error()) {
190 state.deinit(alloc);
191 return extra.error();
192 }
193
194 state->extra = extra.value();
195 auto futureArc = state.acquire(alloc);
196 if (futureArc.is_error()) {
197 state.deinit(alloc);
199 }
200 return make_res{.future = Future<T, E>{.state = futureArc.value()}, .state = state};
201 }
202 };
203
204} // namespace mtcore::thread
205
206#endif // MTCORE_MTTHREAD_FUTURE_HPP
constexpr auto nullopt
Placeholder value for an empty Optional.
Definition optional.hpp:409
AllocationError
Error indicating failed allocation.
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Error< Underlying > error(Underlying err)
Creates an error.
Definition result.hpp:425
Thread-related namespace The methods and classes provided by this class are thread-safe Classes and m...
Represents a memory allocator Exact behavior depends on the underlying VTable used Should use the a_*...
Represents a value that may or may not exist (an "Optional" value) Similar concept to std::optional,...
Definition optional.hpp:235
Represents a Result that may have an error (error code) or a success value A type of "void" means the...
Definition result.hpp:170
Automic Reference Count.
Definition arc.hpp:190
Result< Arc, ArcError > acquire(Allocator &alloc)
Acquires a new Arc reference (increments ref count by 1)
Definition arc.hpp:308
void deinit(Allocator &alloc)
Definition arc.hpp:343
Result< void, AllocationError > init(Allocator &alloc, Args... args)
Tries to initialize an ARC to point to a new object.
Definition arc.hpp:282
T wait()
Called by the future, don't call this directly.
Definition future.hpp:101
void set_val(const T &v)
Sets the value of the associated future.
Definition future.hpp:93
static Result< make_res, AllocationError > make(Allocator &alloc)
Makes a future and associated future state.
Definition future.hpp:118
std::condition_variable cv
Definition future.hpp:89
Represents the state-setter part of a future.
Definition future.hpp:141
T wait()
Called by the future, don't call this directly.
Definition future.hpp:156
static Result< make_res, AllocationError > make(Allocator &alloc, std::function< Result< Arc< E >, AllocationError >(Allocator &alloc, Arc< FutureState > &)> getExtra)
Makes a future and associated future state.
Definition future.hpp:182
void deinit(Allocator &alloc)
Definition future.hpp:164
std::condition_variable cv
Definition future.hpp:143
void set_val(const T &v)
Definition future.hpp:147
Represents a value that will be made available in the future Can wait on the value for when it is rea...
Definition future.hpp:50
T wait()
Blocks to wait for result.
Definition future.hpp:68
Arc< FutureState< T, E > > state
Definition future.hpp:51
Result< Future, ArcError > acquire(Allocator &alloc)
Acquires a new reference to the future (if you want multiple parts of your code to read it)
Definition future.hpp:57
void deinit(Allocator &alloc)
Cleans up future.
Definition future.hpp:74