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