WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
future.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <stdint.h>
8
9#include <algorithm>
10#include <atomic>
11#include <chrono>
12#include <functional>
13#include <type_traits>
14#include <utility>
15#include <vector>
16
18#include "wpi/util/mutex.hpp"
19
20namespace wpi::util {
21
22template <typename T>
23class PromiseFactory;
24
25template <typename T>
26class future;
27
28template <typename T>
29class promise;
30template <>
31class promise<void>;
32
33namespace detail {
34
36 public:
38
39 bool IsActive() const { return m_active; }
40
41 wpi::util::mutex& GetResultMutex() { return m_resultMutex; }
42
43 void Notify() { m_resultCv.notify_all(); }
44
45 // must be called with locked lock == ResultMutex
46 void Wait(std::unique_lock<wpi::util::mutex>& lock) { m_resultCv.wait(lock); }
47
48 // returns false if timeout reached
49 template <class Clock, class Duration>
50 bool WaitUntil(std::unique_lock<wpi::util::mutex>& lock,
51 const std::chrono::time_point<Clock, Duration>& timeout_time) {
52 return m_resultCv.wait_until(lock, timeout_time) ==
53 std::cv_status::no_timeout;
54 }
55
56 void IgnoreResult(uint64_t request);
57
58 uint64_t CreateRequest();
59
60 // returns true if request was pending
61 // must be called with ResultMutex held
62 bool EraseRequest(uint64_t request);
63
64 // same as doing CreateRequest() followed by EraseRequest()
65 // must be called with ResultMutex held
66 uint64_t CreateErasedRequest() { return ++m_uid; }
67
68 private:
69 wpi::util::mutex m_resultMutex;
70 std::atomic_bool m_active{true};
72
73 uint64_t m_uid = 0;
74 std::vector<uint64_t> m_requests;
75};
76
77template <typename To, typename From>
78struct FutureThen {
79 template <typename F>
80 static future<To> Create(PromiseFactory<From>& fromFactory, uint64_t request,
81 PromiseFactory<To>& factory, F&& func);
82};
83
84template <typename From>
85struct FutureThen<void, From> {
86 template <typename F>
87 static future<void> Create(PromiseFactory<From>& fromFactory,
88 uint64_t request, PromiseFactory<void>& factory,
89 F&& func);
90};
91
92template <typename To>
93struct FutureThen<To, void> {
94 template <typename F>
95 static future<To> Create(PromiseFactory<void>& fromFactory, uint64_t request,
96 PromiseFactory<To>& factory, F&& func);
97};
98
99template <>
100struct FutureThen<void, void> {
101 template <typename F>
103 uint64_t request, PromiseFactory<void>& factory,
104 F&& func);
105};
106
107} // namespace detail
108
109/**
110 * A promise factory for lightweight futures.
111 *
112 * The lifetime of the factory must be ensured to be longer than any futures
113 * it creates.
114 *
115 * Use CreateRequest() to create the future request id, and then CreateFuture()
116 * and CreatePromise() to create future and promise objects. A promise should
117 * only be created once for any given request id.
118 *
119 * @tparam T the "return" type of the promise/future
120 */
121template <typename T>
123 friend class future<T>;
124
125 public:
127 using ThenFunction = std::function<void(uint64_t, T)>;
128
129 /**
130 * Creates a future.
131 *
132 * @param request the request id returned by CreateRequest()
133 * @return the future
134 */
135 future<T> CreateFuture(uint64_t request);
136
137 /**
138 * Creates a future and makes it immediately ready.
139 *
140 * @return the future
141 */
143
144 /**
145 * Creates a promise.
146 *
147 * @param request the request id returned by CreateRequest()
148 * @return the promise
149 */
150 promise<T> CreatePromise(uint64_t request);
151
152 /**
153 * Sets a value directly for a future without creating a promise object.
154 * Identical to `CreatePromise(request).set_value(value)`.
155 *
156 * @param request request id, as returned by CreateRequest()
157 * @param value lvalue
158 */
159 void SetValue(uint64_t request, const T& value);
160
161 /**
162 * Sets a value directly for a future without creating a promise object.
163 * Identical to `CreatePromise(request).set_value(value)`.
164 *
165 * @param request request id, as returned by CreateRequest()
166 * @param value rvalue
167 */
168 void SetValue(uint64_t request, T&& value);
169
170 void SetThen(uint64_t request, uint64_t outRequest, ThenFunction func);
171
172 bool IsReady(uint64_t request) noexcept;
173 T GetResult(uint64_t request);
174 void WaitResult(uint64_t request);
175 template <class Clock, class Duration>
177 uint64_t request,
178 const std::chrono::time_point<Clock, Duration>& timeout_time);
179
181
182 private:
183 struct Then {
184 Then(uint64_t request_, uint64_t outRequest_, ThenFunction func_)
185 : request(request_), outRequest(outRequest_), func(std::move(func_)) {}
186 uint64_t request;
187 uint64_t outRequest;
189 };
190
191 std::vector<Then> m_thens;
192 std::vector<std::pair<uint64_t, T>> m_results;
193};
194
195/**
196 * Explicit specialization for PromiseFactory<void>.
197 */
198template <>
199class PromiseFactory<void> final : public detail::PromiseFactoryBase {
200 friend class future<void>;
201
202 public:
204 using ThenFunction = std::function<void(uint64_t)>;
205
206 /**
207 * Creates a future.
208 *
209 * @param request the request id returned by CreateRequest()
210 * @return std::pair of the future and the request id
211 */
212 future<void> CreateFuture(uint64_t request);
213
214 /**
215 * Creates a future and makes it immediately ready.
216 *
217 * @return the future
218 */
220
221 /**
222 * Creates a promise.
223 *
224 * @param request the request id returned by CreateRequest()
225 * @return the promise
226 */
227 promise<void> CreatePromise(uint64_t request);
228
229 /**
230 * Sets a value directly for a future without creating a promise object.
231 * Identical to `promise(factory, request).set_value()`.
232 *
233 * @param request request id, as returned by CreateRequest()
234 */
235 void SetValue(uint64_t request);
236
237 void SetThen(uint64_t request, uint64_t outRequest, ThenFunction func);
238
239 bool IsReady(uint64_t request) noexcept;
240 void GetResult(uint64_t request);
241 void WaitResult(uint64_t request);
242 template <class Clock, class Duration>
243 bool WaitResultUntil(
244 uint64_t request,
245 const std::chrono::time_point<Clock, Duration>& timeout_time);
246
248
249 private:
250 struct Then {
251 Then(uint64_t request_, uint64_t outRequest_, ThenFunction func_)
252 : request(request_), outRequest(outRequest_), func(std::move(func_)) {}
253 uint64_t request;
254 uint64_t outRequest;
256 };
257
258 std::vector<Then> m_thens;
259 std::vector<uint64_t> m_results;
260};
261
262/**
263 * A lightweight version of std::future.
264 *
265 * Use either promise::get_future() or PromiseFactory::CreateFuture() to create.
266 *
267 * @tparam T the "return" type
268 */
269template <typename T>
270class future final {
271 friend class PromiseFactory<T>;
272 friend class promise<T>;
273
274 public:
275 /**
276 * Constructs an empty (invalid) future.
277 */
278 future() noexcept = default;
279
280 future(future&& oth) noexcept {
281 this->m_request = oth.m_request;
282 this->m_promises = oth.m_promises;
283 oth.m_request = 0;
284 oth.m_promises = nullptr;
285 }
286 future(const future&) = delete;
287
288 template <typename R>
289 future(future<R>&& oth) noexcept // NOLINT
290 : future(oth.then([](R&& val) -> T { return val; })) {}
291
292 /**
293 * Ignores the result of the future if it has not been retrieved.
294 */
296 if (m_promises) {
297 m_promises->IgnoreResult(m_request);
298 }
299 }
300
301 future& operator=(future&& oth) noexcept {
302 this->m_request = oth.m_request;
303 this->m_promises = oth.m_promises;
304 oth.m_request = 0;
305 oth.m_promises = nullptr;
306 return *this;
307 }
308 future& operator=(const future&) = delete;
309
310 /**
311 * Gets the value. Calls wait() if the value is not yet available.
312 * Can only be called once. The future will be marked invalid after the call.
313 *
314 * @return The value provided by the corresponding promise.set_value().
315 */
316 T get() {
317 if (m_promises) {
318 return m_promises->GetResult(m_request);
319 } else {
320 return T();
321 }
322 }
323
324 template <typename R, typename F>
325 future<R> then(PromiseFactory<R>& factory, F&& func) {
326 if (m_promises) {
327 auto promises = m_promises;
328 m_promises = nullptr;
329 return detail::FutureThen<R, T>::Create(*promises, m_request, factory,
330 func);
331 } else {
332 return future<R>();
333 }
334 }
335
336 template <typename F, typename R = typename std::invoke_result_t<F&&, T&&>>
337 future<R> then(F&& func) {
338 return then(PromiseFactory<R>::GetInstance(), std::forward<F>(func));
339 }
340
341 bool is_ready() const noexcept {
342 return m_promises && m_promises->IsReady(m_request);
343 }
344
345 /**
346 * Checks if the future is valid.
347 * A default-constructed future or one where get() has been called is invalid.
348 *
349 * @return True if valid
350 */
351 bool valid() const noexcept { return m_promises; }
352
353 /**
354 * Waits for the promise to provide a value.
355 * Does not return until the value is available or the promise is destroyed
356 * (in which case a default-constructed value is "returned").
357 * If the value has already been provided, returns immediately.
358 */
359 void wait() const {
360 if (m_promises) {
361 m_promises->WaitResult(m_request);
362 }
363 }
364
365 /**
366 * Waits for the promise to provide a value, or the specified time has been
367 * reached.
368 *
369 * @return True if the promise provided a value, false if timed out.
370 */
371 template <class Clock, class Duration>
373 const std::chrono::time_point<Clock, Duration>& timeout_time) const {
374 return m_promises && m_promises->WaitResultUntil(m_request, timeout_time);
375 }
376
377 /**
378 * Waits for the promise to provide a value, or the specified amount of time
379 * has elapsed.
380 *
381 * @return True if the promise provided a value, false if timed out.
382 */
383 template <class Rep, class Period>
385 const std::chrono::duration<Rep, Period>& timeout_duration) const {
386 return wait_until(std::chrono::steady_clock::now() + timeout_duration);
387 }
388
389 private:
390 future(PromiseFactory<T>* promises, uint64_t request) noexcept
391 : m_request(request), m_promises(promises) {}
392
393 uint64_t m_request = 0;
394 PromiseFactory<T>* m_promises = nullptr;
395};
396
397/**
398 * Explicit specialization for future<void>.
399 */
400template <>
401class future<void> final {
402 friend class PromiseFactory<void>;
403 friend class promise<void>;
404
405 public:
406 /**
407 * Constructs an empty (invalid) future.
408 */
409 future() noexcept = default;
410
411 future(future&& oth) noexcept {
412 m_request = oth.m_request;
413 m_promises = oth.m_promises;
414 oth.m_request = 0;
415 oth.m_promises = nullptr;
416 }
417 future(const future&) = delete;
418
419 /**
420 * Ignores the result of the future if it has not been retrieved.
421 */
423 if (m_promises) {
424 m_promises->IgnoreResult(m_request);
425 }
426 }
427
428 future& operator=(future&& oth) noexcept {
429 m_request = oth.m_request;
430 m_promises = oth.m_promises;
431 oth.m_request = 0;
432 oth.m_promises = nullptr;
433 return *this;
434 }
435 future& operator=(const future&) = delete;
436
437 /**
438 * Gets the value. Calls wait() if the value is not yet available.
439 * Can only be called once. The future will be marked invalid after the call.
440 */
441 void get() {
442 if (m_promises) {
443 m_promises->GetResult(m_request);
444 }
445 }
446
447 template <typename R, typename F>
448 future<R> then(PromiseFactory<R>& factory, F&& func) {
449 if (m_promises) {
450 auto promises = m_promises;
451 m_promises = nullptr;
452 return detail::FutureThen<R, void>::Create(*promises, m_request, factory,
453 func);
454 } else {
455 return future<R>();
456 }
457 }
458
459 template <typename F, typename R = typename std::invoke_result_t<F&&>>
460 future<R> then(F&& func) {
461 return then(PromiseFactory<R>::GetInstance(), std::forward<F>(func));
462 }
463
464 bool is_ready() const noexcept {
465 return m_promises && m_promises->IsReady(m_request);
466 }
467
468 /**
469 * Checks if the future is valid.
470 * A default-constructed future or one where get() has been called is invalid.
471 *
472 * @return True if valid
473 */
474 bool valid() const noexcept { return m_promises; }
475
476 /**
477 * Waits for the promise to provide a value.
478 * Does not return until the value is available or the promise is destroyed
479 * If the value has already been provided, returns immediately.
480 */
481 void wait() const {
482 if (m_promises) {
483 m_promises->WaitResult(m_request);
484 }
485 }
486
487 /**
488 * Waits for the promise to provide a value, or the specified time has been
489 * reached.
490 *
491 * @return True if the promise provided a value, false if timed out.
492 */
493 template <class Clock, class Duration>
495 const std::chrono::time_point<Clock, Duration>& timeout_time) const {
496 return m_promises && m_promises->WaitResultUntil(m_request, timeout_time);
497 }
498
499 /**
500 * Waits for the promise to provide a value, or the specified amount of time
501 * has elapsed.
502 *
503 * @return True if the promise provided a value, false if timed out.
504 */
505 template <class Rep, class Period>
507 const std::chrono::duration<Rep, Period>& timeout_duration) const {
508 return wait_until(std::chrono::steady_clock::now() + timeout_duration);
509 }
510
511 private:
512 future(PromiseFactory<void>* promises, uint64_t request) noexcept
513 : m_request(request), m_promises(promises) {}
514
515 uint64_t m_request = 0;
516 PromiseFactory<void>* m_promises = nullptr;
517};
518
519/**
520 * A lightweight version of std::promise.
521 *
522 * Use PromiseFactory::CreatePromise() to create.
523 *
524 * @tparam T the "return" type
525 */
526template <typename T>
527class promise final {
528 friend class PromiseFactory<T>;
529
530 public:
531 /**
532 * Constructs an empty promise.
533 */
534 promise() : m_promises(&PromiseFactory<T>::GetInstance()) {
535 m_request = m_promises->CreateRequest();
536 }
537
538 promise(promise&& oth) noexcept
539 : m_request(oth.m_request), m_promises(oth.m_promises) {
540 oth.m_request = 0;
541 oth.m_promises = nullptr;
542 }
543
544 promise(const promise&) = delete;
545
546 /**
547 * Sets the promised value to a default-constructed T if not already set.
548 */
550 if (m_promises) {
551 m_promises->SetValue(m_request, T());
552 }
553 }
554
555 promise& operator=(promise&& oth) noexcept {
556 m_request = oth.m_request;
557 m_promises = oth.m_promises;
558 oth.m_request = 0;
559 oth.m_promises = nullptr;
560 return *this;
561 }
562
563 promise& operator=(const promise&) = delete;
564
565 /**
566 * Swaps this promise with another one.
567 */
568 void swap(promise& oth) noexcept {
569 std::swap(m_request, oth.m_request);
570 std::swap(m_promises, oth.m_promises);
571 }
572
573 /**
574 * Gets a future for this promise.
575 *
576 * @return The future
577 */
578 future<T> get_future() noexcept { return future<T>(m_promises, m_request); }
579
580 /**
581 * Sets the promised value.
582 * Only effective once (subsequent calls will be ignored).
583 *
584 * @param value The value to provide to the waiting future
585 */
586 void set_value(const T& value) {
587 if (m_promises) {
588 m_promises->SetValue(m_request, value);
589 }
590 m_promises = nullptr;
591 }
592
593 /**
594 * Sets the promised value.
595 * Only effective once (subsequent calls will be ignored).
596 *
597 * @param value The value to provide to the waiting future
598 */
599 void set_value(T&& value) {
600 if (m_promises) {
601 m_promises->SetValue(m_request, std::move(value));
602 }
603 m_promises = nullptr;
604 }
605
606 private:
607 promise(PromiseFactory<T>* promises, uint64_t request) noexcept
608 : m_request(request), m_promises(promises) {}
609
610 uint64_t m_request = 0;
611 PromiseFactory<T>* m_promises = nullptr;
612};
613
614/**
615 * Explicit specialization for promise<void>.
616 */
617template <>
618class promise<void> final {
619 friend class PromiseFactory<void>;
620
621 public:
622 /**
623 * Constructs an empty promise.
624 */
625 promise() : m_promises(&PromiseFactory<void>::GetInstance()) {
626 m_request = m_promises->CreateRequest();
627 }
628
629 promise(promise&& oth) noexcept
630 : m_request(oth.m_request), m_promises(oth.m_promises) {
631 oth.m_request = 0;
632 oth.m_promises = nullptr;
633 }
634
635 promise(const promise&) = delete;
636
637 /**
638 * Sets the promised value if not already set.
639 */
641 if (m_promises) {
642 m_promises->SetValue(m_request);
643 }
644 }
645
646 promise& operator=(promise&& oth) noexcept {
647 m_request = oth.m_request;
648 m_promises = oth.m_promises;
649 oth.m_request = 0;
650 oth.m_promises = nullptr;
651 return *this;
652 }
653
654 promise& operator=(const promise&) = delete;
655
656 /**
657 * Swaps this promise with another one.
658 */
659 void swap(promise& oth) noexcept {
660 std::swap(m_request, oth.m_request);
661 std::swap(m_promises, oth.m_promises);
662 }
663
664 /**
665 * Gets a future for this promise.
666 *
667 * @return The future
668 */
670 return future<void>(m_promises, m_request);
671 }
672
673 /**
674 * Sets the promised value.
675 * Only effective once (subsequent calls will be ignored).
676 */
677 void set_value() {
678 if (m_promises) {
679 m_promises->SetValue(m_request);
680 }
681 m_promises = nullptr;
682 }
683
684 private:
685 promise(PromiseFactory<void>* promises, uint64_t request) noexcept
686 : m_request(request), m_promises(promises) {}
687
688 uint64_t m_request = 0;
689 PromiseFactory<void>* m_promises = nullptr;
690};
691
692/**
693 * Constructs a valid future with the value set.
694 */
695template <typename T>
696inline future<T> make_ready_future(T&& value) {
698 std::forward<T>(value));
699}
700
701/**
702 * Constructs a valid future with the value set.
703 */
707
708template <typename T>
710 return future<T>{this, request};
711}
712
713template <typename T>
715 std::unique_lock lock(GetResultMutex());
716 uint64_t req = CreateErasedRequest();
717 m_results.emplace_back(std::piecewise_construct, std::forward_as_tuple(req),
718 std::forward_as_tuple(std::move(value)));
719 return future<T>{this, req};
720}
721
722template <typename T>
724 return promise<T>{this, request};
725}
726
727template <typename T>
728void PromiseFactory<T>::SetValue(uint64_t request, const T& value) {
729 std::unique_lock lock(GetResultMutex());
730 if (!EraseRequest(request)) {
731 return;
732 }
733 auto it = std::find_if(m_thens.begin(), m_thens.end(),
734 [=](const auto& x) { return x.request == request; });
735 if (it != m_thens.end()) {
736 uint64_t outRequest = it->outRequest;
737 ThenFunction func = std::move(it->func);
738 m_thens.erase(it);
739 lock.unlock();
740 return func(outRequest, value);
741 }
742 m_results.emplace_back(std::piecewise_construct,
743 std::forward_as_tuple(request),
744 std::forward_as_tuple(value));
745 Notify();
746}
747
748template <typename T>
749void PromiseFactory<T>::SetValue(uint64_t request, T&& value) {
750 std::unique_lock lock(GetResultMutex());
751 if (!EraseRequest(request)) {
752 return;
753 }
754 auto it = std::find_if(m_thens.begin(), m_thens.end(),
755 [=](const auto& x) { return x.request == request; });
756 if (it != m_thens.end()) {
757 uint64_t outRequest = it->outRequest;
758 ThenFunction func = std::move(it->func);
759 m_thens.erase(it);
760 lock.unlock();
761 return func(outRequest, std::move(value));
762 }
763 m_results.emplace_back(std::piecewise_construct,
764 std::forward_as_tuple(request),
765 std::forward_as_tuple(std::move(value)));
766 Notify();
767}
768
769template <typename T>
770void PromiseFactory<T>::SetThen(uint64_t request, uint64_t outRequest,
771 ThenFunction func) {
772 std::unique_lock lock(GetResultMutex());
773 auto it = std::find_if(m_results.begin(), m_results.end(),
774 [=](const auto& r) { return r.first == request; });
775 if (it != m_results.end()) {
776 auto val = std::move(it->second);
777 m_results.erase(it);
778 lock.unlock();
779 return func(outRequest, std::move(val));
780 }
781 m_thens.emplace_back(request, outRequest, func);
782}
783
784template <typename T>
785bool PromiseFactory<T>::IsReady(uint64_t request) noexcept {
786 std::unique_lock lock(GetResultMutex());
787 auto it = std::find_if(m_results.begin(), m_results.end(),
788 [=](const auto& r) { return r.first == request; });
789 return it != m_results.end();
790}
791
792template <typename T>
793T PromiseFactory<T>::GetResult(uint64_t request) {
794 // wait for response
795 std::unique_lock lock(GetResultMutex());
796 while (IsActive()) {
797 // Did we get a response to *our* request?
798 auto it = std::find_if(m_results.begin(), m_results.end(),
799 [=](const auto& r) { return r.first == request; });
800 if (it != m_results.end()) {
801 // Yes, remove it from the vector and we're done.
802 auto rv = std::move(it->second);
803 m_results.erase(it);
804 return rv;
805 }
806 // No, keep waiting for a response
807 Wait(lock);
808 }
809 return T();
810}
811
812template <typename T>
813void PromiseFactory<T>::WaitResult(uint64_t request) {
814 // wait for response
815 std::unique_lock lock(GetResultMutex());
816 while (IsActive()) {
817 // Did we get a response to *our* request?
818 auto it = std::find_if(m_results.begin(), m_results.end(),
819 [=](const auto& r) { return r.first == request; });
820 if (it != m_results.end()) {
821 return;
822 }
823 // No, keep waiting for a response
824 Wait(lock);
825 }
826}
827
828template <typename T>
829template <class Clock, class Duration>
831 uint64_t request,
832 const std::chrono::time_point<Clock, Duration>& timeout_time) {
833 std::unique_lock lock(GetResultMutex());
834 bool timeout = false;
835 while (IsActive()) {
836 // Did we get a response to *our* request?
837 auto it = std::find_if(m_results.begin(), m_results.end(),
838 [=](const auto& r) { return r.first == request; });
839 if (it != m_results.end()) {
840 return true;
841 }
842 if (timeout) {
843 break;
844 }
845 // No, keep waiting for a response
846 if (!WaitUntil(lock, timeout_time)) {
847 timeout = true;
848 }
849 }
850 return false;
851}
852
853template <typename T>
855 static PromiseFactory inst;
856 return inst;
857}
858
860 return future<void>{this, request};
861}
862
864 return promise<void>{this, request};
865}
866
867template <class Clock, class Duration>
869 uint64_t request,
870 const std::chrono::time_point<Clock, Duration>& timeout_time) {
871 std::unique_lock lock(GetResultMutex());
872 bool timeout = false;
873 while (IsActive()) {
874 // Did we get a response to *our* request?
875 auto it = std::find_if(m_results.begin(), m_results.end(),
876 [=](const auto& r) { return r == request; });
877 if (it != m_results.end()) {
878 return true;
879 }
880 if (timeout) {
881 break;
882 }
883 // No, keep waiting for a response
884 if (!WaitUntil(lock, timeout_time)) {
885 timeout = true;
886 }
887 }
888 return false;
889}
890
891template <typename To, typename From>
892template <typename F>
894 PromiseFactory<From>& fromFactory, uint64_t request,
895 PromiseFactory<To>& factory, F&& func) {
896 uint64_t req = factory.CreateRequest();
897 fromFactory.SetThen(request, req, [&factory, func](uint64_t r, From value) {
898 factory.SetValue(r, func(std::move(value)));
899 });
900 return factory.CreateFuture(req);
901}
902
903template <typename From>
904template <typename F>
906 PromiseFactory<From>& fromFactory, uint64_t request,
907 PromiseFactory<void>& factory, F&& func) {
908 uint64_t req = factory.CreateRequest();
909 fromFactory.SetThen(request, req, [&factory, func](uint64_t r, From value) {
910 func(std::move(value));
911 factory.SetValue(r);
912 });
913 return factory.CreateFuture(req);
914}
915
916template <typename To>
917template <typename F>
919 PromiseFactory<void>& fromFactory, uint64_t request,
920 PromiseFactory<To>& factory, F&& func) {
921 uint64_t req = factory.CreateRequest();
922 fromFactory.SetThen(request, req, [&factory, func](uint64_t r) {
923 factory.SetValue(r, func());
924 });
925 return factory.CreateFuture(req);
926}
927
928template <typename F>
930 PromiseFactory<void>& fromFactory, uint64_t request,
931 PromiseFactory<void>& factory, F&& func) {
932 uint64_t req = factory.CreateRequest();
933 fromFactory.SetThen(request, req, [&factory, func](uint64_t r) {
934 func();
935 factory.SetValue(r);
936 });
937 return factory.CreateFuture(req);
938}
939
940} // namespace wpi::util
void WaitResult(uint64_t request)
void GetResult(uint64_t request)
void SetValue(uint64_t request)
Sets a value directly for a future without creating a promise object.
void SetThen(uint64_t request, uint64_t outRequest, ThenFunction func)
std::function< void(uint64_t)> ThenFunction
Definition future.hpp:204
future< void > MakeReadyFuture()
Creates a future and makes it immediately ready.
static PromiseFactory & GetInstance()
bool IsReady(uint64_t request) noexcept
A promise factory for lightweight futures.
Definition future.hpp:122
future< T > MakeReadyFuture(T &&value)
Creates a future and makes it immediately ready.
Definition future.hpp:714
std::function< void(uint64_t, T)> ThenFunction
Definition future.hpp:127
static PromiseFactory & GetInstance()
Definition future.hpp:854
bool IsReady(uint64_t request) noexcept
Definition future.hpp:785
T GetResult(uint64_t request)
Definition future.hpp:793
void WaitResult(uint64_t request)
Definition future.hpp:813
void SetThen(uint64_t request, uint64_t outRequest, ThenFunction func)
Definition future.hpp:770
future< T > CreateFuture(uint64_t request)
Creates a future.
Definition future.hpp:709
void SetValue(uint64_t request, const T &value)
Sets a value directly for a future without creating a promise object.
Definition future.hpp:728
promise< T > CreatePromise(uint64_t request)
Creates a promise.
Definition future.hpp:723
void Notify()
Definition future.hpp:43
bool WaitResultUntil(uint64_t request, const std::chrono::time_point< Clock, Duration > &timeout_time)
Definition future.hpp:830
wpi::util::mutex & GetResultMutex()
Definition future.hpp:41
uint64_t CreateErasedRequest()
Definition future.hpp:66
void Wait(std::unique_lock< wpi::util::mutex > &lock)
Definition future.hpp:46
void IgnoreResult(uint64_t request)
void Notify()
Definition future.hpp:43
bool EraseRequest(uint64_t request)
bool IsActive() const
Definition future.hpp:39
bool WaitUntil(std::unique_lock< wpi::util::mutex > &lock, const std::chrono::time_point< Clock, Duration > &timeout_time)
Definition future.hpp:50
bool wait_for(const std::chrono::duration< Rep, Period > &timeout_duration) const
Waits for the promise to provide a value, or the specified amount of time has elapsed.
Definition future.hpp:506
bool is_ready() const noexcept
Definition future.hpp:464
void wait() const
Waits for the promise to provide a value.
Definition future.hpp:481
future & operator=(future &&oth) noexcept
Definition future.hpp:428
future & operator=(const future &)=delete
void get()
Gets the value.
Definition future.hpp:441
future() noexcept=default
Constructs an empty (invalid) future.
~future()
Ignores the result of the future if it has not been retrieved.
Definition future.hpp:422
future(const future &)=delete
bool wait_until(const std::chrono::time_point< Clock, Duration > &timeout_time) const
Waits for the promise to provide a value, or the specified time has been reached.
Definition future.hpp:494
bool valid() const noexcept
Checks if the future is valid.
Definition future.hpp:474
future< R > then(PromiseFactory< R > &factory, F &&func)
Definition future.hpp:448
future< R > then(F &&func)
Definition future.hpp:460
A lightweight version of std::future.
Definition future.hpp:270
future & operator=(const future &)=delete
future & operator=(future &&oth) noexcept
Definition future.hpp:301
future< R > then(F &&func)
Definition future.hpp:337
T get()
Gets the value.
Definition future.hpp:316
bool valid() const noexcept
Checks if the future is valid.
Definition future.hpp:351
future< R > then(PromiseFactory< R > &factory, F &&func)
Definition future.hpp:325
~future()
Ignores the result of the future if it has not been retrieved.
Definition future.hpp:295
bool wait_for(const std::chrono::duration< Rep, Period > &timeout_duration) const
Waits for the promise to provide a value, or the specified amount of time has elapsed.
Definition future.hpp:384
future(future< R > &&oth) noexcept
Definition future.hpp:289
bool wait_until(const std::chrono::time_point< Clock, Duration > &timeout_time) const
Waits for the promise to provide a value, or the specified time has been reached.
Definition future.hpp:372
future() noexcept=default
Constructs an empty (invalid) future.
void wait() const
Waits for the promise to provide a value.
Definition future.hpp:359
bool is_ready() const noexcept
Definition future.hpp:341
future(const future &)=delete
promise(const promise &)=delete
promise()
Constructs an empty promise.
Definition future.hpp:625
promise(promise &&oth) noexcept
Definition future.hpp:629
promise & operator=(const promise &)=delete
promise & operator=(promise &&oth) noexcept
Definition future.hpp:646
~promise()
Sets the promised value if not already set.
Definition future.hpp:640
void swap(promise &oth) noexcept
Swaps this promise with another one.
Definition future.hpp:659
future< void > get_future() noexcept
Gets a future for this promise.
Definition future.hpp:669
void set_value()
Sets the promised value.
Definition future.hpp:677
A lightweight version of std::promise.
Definition future.hpp:527
promise(const promise &)=delete
~promise()
Sets the promised value to a default-constructed T if not already set.
Definition future.hpp:549
promise(promise &&oth) noexcept
Definition future.hpp:538
promise & operator=(promise &&oth) noexcept
Definition future.hpp:555
future< T > get_future() noexcept
Gets a future for this promise.
Definition future.hpp:578
promise & operator=(const promise &)=delete
void swap(promise &oth) noexcept
Swaps this promise with another one.
Definition future.hpp:568
void set_value(const T &value)
Sets the promised value.
Definition future.hpp:586
void set_value(T &&value)
Sets the promised value.
Definition future.hpp:599
promise()
Constructs an empty promise.
Definition future.hpp:534
Definition StringMap.hpp:773
void swap(wpi::util::StringMap< T > &lhs, wpi::util::StringMap< T > &rhs)
Definition StringMap.hpp:775
These are wrappers over isa* function that allow them to be used in generic algorithms such as wpi::u...
Definition type_traits.hpp:71
Definition raw_os_ostream.hpp:19
::std::condition_variable condition_variable
Definition condition_variable.hpp:16
future< void > make_ready_future()
Constructs a valid future with the value set.
Definition future.hpp:704
::std::mutex mutex
Definition mutex.hpp:17
void Wait(wpi::units::second_t seconds)
Pause the task for a specified time.
Definition future.hpp:78
static future< To > Create(PromiseFactory< From > &fromFactory, uint64_t request, PromiseFactory< To > &factory, F &&func)
Definition future.hpp:893