OGLplus  (0.59.0) a C++ wrapper for rendering APIs

future.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_MESSAGE_BUS_FUTURE_HPP
10 #define EAGINE_MESSAGE_BUS_FUTURE_HPP
11 
12 #include "../flat_map.hpp"
13 #include "../nothing.hpp"
14 #include "../timeout.hpp"
15 #include <functional>
16 #include <memory>
17 
18 namespace eagine::msgbus {
19 //------------------------------------------------------------------------------
20 template <typename T>
21 struct future_state {
22  timeout too_late{std::chrono::seconds{1}};
23  std::function<void(T)> success_handler{};
24  std::function<void()> timeout_handler{};
25 };
26 //------------------------------------------------------------------------------
31 template <typename T>
32 class promise {
33 public:
35  promise() noexcept = default;
36 
37  promise(std::shared_ptr<future_state<T>>& state) noexcept
38  : _state{state} {}
39 
40  auto should_be_removed() -> bool {
41  if(auto state{_state.lock()}) {
42  if(state->too_late) {
43  if(state->timeout_handler) {
44  state->timeout_handler();
45  _state.reset();
46  }
47  } else {
48  return false;
49  }
50  }
51  return true;
52  }
53 
55  void fulfill(T value) {
56  if(auto state{_state.lock()}) {
57  _state.reset();
58  if(state->too_late) {
59  if(state->timeout_handler) {
60  state->timeout_handler();
61  }
62  } else {
63  if(state->success_handler) {
64  state->success_handler(std::move(value));
65  }
66  }
67  }
68  }
69 
70 private:
71  std::weak_ptr<future_state<T>> _state{};
72 };
73 //------------------------------------------------------------------------------
78 template <typename T>
79 class future {
80 public:
82  future() = default;
83 
85  future(nothing_t) noexcept
86  : _state{} {}
87 
89  explicit operator bool() const noexcept {
90  return bool(_state);
91  }
92 
94  template <typename R, typename P>
95  auto set_timeout(std::chrono::duration<R, P> dur) -> future<T>& {
96  if(_state) {
97  _state->too_late.reset(dur);
98  }
99  return *this;
100  }
101 
105  auto on_success(const std::function<void(T)>& handler) -> future<T>& {
106  if(_state) {
107  _state->success_handler = handler;
108  }
109  return *this;
110  }
111 
114  auto on_timeout(const std::function<void()>& handler) -> future<T>& {
115  if(_state) {
116  _state->timeout_handler = handler;
117  }
118  return *this;
119  }
120 
124  template <
125  typename Handler,
126  typename = std::enable_if_t<std::is_invocable_v<Handler, T>>>
127  auto then(Handler handler) -> future<T>& {
128  if(_state) {
129  _state->success_handler = std::function<void(T)>(
130  [state{_state}, handler{std::move(handler)}](T value) {
131  handler(value);
132  });
133  }
134  return *this;
135  }
136 
140  template <
141  typename Handler,
142  typename = std::enable_if_t<std::is_invocable_v<Handler>>>
143  auto otherwise(Handler handler) -> future<T>& {
144  if(_state) {
145  _state->timeout_handler = std::function<void()>(
146  [state{_state}, handler{std::move(handler)}]() { handler(); });
147  }
148  return *this;
149  }
150 
153  return {_state};
154  }
155 
156 private:
157  std::shared_ptr<future_state<T>> _state{
158  std::make_shared<future_state<T>>()};
159 };
160 //------------------------------------------------------------------------------
165 template <typename T>
167 public:
171  auto make() -> std::tuple<message_sequence_t, future<T>> {
172  future<T> result{};
173  const auto id{++_id_seq};
174  _promises[id] = result.get_promise();
175  return {id, result};
176  }
177 
179  void fulfill(message_sequence_t id, T value) {
180  auto pos = _promises.find(id);
181  if(pos != _promises.end()) {
182  pos->second.fulfill(std::move(value));
183  _promises.erase(pos);
184  }
185  update();
186  }
187 
189  auto update() -> bool {
190  return _promises.erase_if(
191  [](auto& p) { return p.second.should_be_removed(); }) > 0;
192  }
193 
196  auto has_some() const noexcept -> bool {
197  return !_promises.empty();
198  }
199 
202  auto has_none() const noexcept -> bool {
203  return _promises.empty();
204  }
205 
206 private:
207  message_sequence_t _id_seq{0};
208  flat_map<message_sequence_t, promise<T>> _promises{};
209 };
210 //------------------------------------------------------------------------------
211 } // namespace eagine::msgbus
212 
213 #endif // EAGINE_MESSAGE_BUS_FUTURE_HPP
Message bus promise class.
Definition: future.hpp:32
auto set_timeout(std::chrono::duration< R, P > dur) -> future< T > &
Sets the timeout for this future if there is shared state.
Definition: future.hpp:95
Class representing "none" / "nothing" values.
Definition: nothing.hpp:17
auto then(Handler handler) -> future< T > &
Wraps the given handler object and sets it as the on-success handler.
Definition: future.hpp:127
auto make() -> std::tuple< message_sequence_t, future< T >>
Constructs and returns a new message bus future and its unique id.
Definition: future.hpp:171
void fulfill(message_sequence_t id, T value)
Fulfills the promise/future pair idenified by id with the given value.
Definition: future.hpp:179
auto on_timeout(const std::function< void()> &handler) -> future< T > &
Sets the on-timeout handler.
Definition: future.hpp:114
auto has_none() const noexcept -> bool
Indicates if there are no pending promises.
Definition: future.hpp:202
auto otherwise(Handler handler) -> future< T > &
Wraps the given handler object and sets it as the on-timeout handler.
Definition: future.hpp:143
std::uint32_t message_sequence_t
Alias for message sequence number type.
Definition: types.hpp:22
auto update() -> bool
Update the internal state of this promise/future tracker.
Definition: future.hpp:189
void fulfill(T value)
Fulfills the promise and the corresponding future.
Definition: future.hpp:55
Message bus code is placed in this namespace.
Definition: eagine.hpp:58
promise() noexcept=default
Default constructor.
auto on_success(const std::function< void(T)> &handler) -> future< T > &
Sets the on-success handler.
Definition: future.hpp:105
auto has_some() const noexcept -> bool
Indicates if there are any unfulfilled pending promises.
Definition: future.hpp:196
future()=default
Default constructor.
Message bus future class.
Definition: future.hpp:79
Class that makes new and tracks existing pending message bus promises.
Definition: future.hpp:166
auto get_promise() -> promise< T >
Returns the associated promise it there is shared state.
Definition: future.hpp:152
future(nothing_t) noexcept
Constructs empty stateless future.
Definition: future.hpp:85

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).