5#ifndef WPIUTIL_WPI_FUTURE_H_
6#define WPIUTIL_WPI_FUTURE_H_
44 void Notify() { m_resultCv.notify_all(); }
47 void Wait(std::unique_lock<wpi::mutex>& lock) { m_resultCv.wait(lock); }
50 template <
class Clock,
class Duration>
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;
71 std::atomic_bool m_active{
true};
75 std::vector<uint64_t> m_requests;
78template <
typename To,
typename From>
85template <
typename From>
102 template <
typename F>
176 template <
class Clock,
class Duration>
179 const std::chrono::time_point<Clock, Duration>& timeout_time);
185 Then(uint64_t request_, uint64_t outRequest_,
ThenFunction func_)
186 : request(request_), outRequest(outRequest_), func(
std::move(func_)) {}
192 std::vector<Then> m_thens;
193 std::vector<std::pair<uint64_t, T>> m_results;
201 friend class future<void>;
243 template <
class Clock,
class Duration>
246 const std::chrono::time_point<Clock, Duration>& timeout_time);
252 Then(uint64_t request_, uint64_t outRequest_,
ThenFunction func_)
253 : request(request_), outRequest(outRequest_), func(
std::move(func_)) {}
259 std::vector<Then> m_thens;
260 std::vector<uint64_t> m_results;
282 this->m_request = oth.m_request;
283 this->m_promises = oth.m_promises;
285 oth.m_promises =
nullptr;
289 template <
typename R>
291 :
future(oth.then([](
R&& val) -> T { return val; })) {}
298 m_promises->IgnoreResult(m_request);
303 this->m_request = oth.m_request;
304 this->m_promises = oth.m_promises;
306 oth.m_promises =
nullptr;
319 return m_promises->GetResult(m_request);
325 template <
typename R,
typename F>
328 auto promises = m_promises;
329 m_promises =
nullptr;
337 template <
typename F,
typename R =
typename std::invoke_result_t<F&&, T&&>>
343 return m_promises && m_promises->IsReady(m_request);
352 bool valid() const noexcept {
return m_promises; }
362 m_promises->WaitResult(m_request);
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);
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);
392 : m_request(request), m_promises(promises) {}
394 uint64_t m_request = 0;
413 m_request = oth.m_request;
414 m_promises = oth.m_promises;
416 oth.m_promises =
nullptr;
425 m_promises->IgnoreResult(m_request);
430 m_request = oth.m_request;
431 m_promises = oth.m_promises;
433 oth.m_promises =
nullptr;
444 m_promises->GetResult(m_request);
448 template <
typename R,
typename F>
451 auto promises = m_promises;
452 m_promises =
nullptr;
460 template <
typename F,
typename R =
typename std::invoke_result_t<F&&>>
466 return m_promises && m_promises->IsReady(m_request);
475 bool valid() const noexcept {
return m_promises; }
484 m_promises->WaitResult(m_request);
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);
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);
514 : m_request(request), m_promises(promises) {}
516 uint64_t m_request = 0;
536 m_request = m_promises->CreateRequest();
540 : m_request(oth.m_request), m_promises(oth.m_promises) {
542 oth.m_promises =
nullptr;
552 m_promises->SetValue(m_request, T());
557 m_request = oth.m_request;
558 m_promises = oth.m_promises;
560 oth.m_promises =
nullptr;
589 m_promises->SetValue(m_request, value);
591 m_promises =
nullptr;
602 m_promises->SetValue(m_request, std::move(value));
604 m_promises =
nullptr;
609 : m_request(request), m_promises(promises) {}
611 uint64_t m_request = 0;
627 m_request = m_promises->CreateRequest();
631 : m_request(oth.m_request), m_promises(oth.m_promises) {
633 oth.m_promises =
nullptr;
643 m_promises->SetValue(m_request);
648 m_request = oth.m_request;
649 m_promises = oth.m_promises;
651 oth.m_promises =
nullptr;
680 m_promises->SetValue(m_request);
682 m_promises =
nullptr;
687 : m_request(request), m_promises(promises) {}
689 uint64_t m_request = 0;
690 PromiseFactory<void>* m_promises =
nullptr;
699 std::forward<T>(value));
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)));
730 std::unique_lock lock(GetResultMutex());
731 if (!EraseRequest(request)) {
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;
741 return func(outRequest, value);
743 m_results.emplace_back(std::piecewise_construct,
744 std::forward_as_tuple(request),
745 std::forward_as_tuple(value));
751 std::unique_lock lock(GetResultMutex());
752 if (!EraseRequest(request)) {
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;
762 return func(outRequest, std::move(value));
764 m_results.emplace_back(std::piecewise_construct,
765 std::forward_as_tuple(request),
766 std::forward_as_tuple(std::move(value)));
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);
780 return func(outRequest, std::move(val));
782 m_thens.emplace_back(request, outRequest, func);
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();
796 std::unique_lock lock(GetResultMutex());
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()) {
803 auto rv = std::move(it->second);
816 std::unique_lock lock(GetResultMutex());
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()) {
830template <
class Clock,
class Duration>
833 const std::chrono::time_point<Clock, Duration>& timeout_time) {
834 std::unique_lock lock(GetResultMutex());
835 bool timeout =
false;
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()) {
868template <
class Clock,
class Duration>
871 const std::chrono::time_point<Clock, Duration>& timeout_time) {
873 bool timeout =
false;
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()) {
892template <
typename To,
typename From>
898 fromFactory.
SetThen(request, req, [&factory, func](uint64_t r, From value) {
899 factory.
SetValue(r, func(std::move(value)));
904template <
typename From>
910 fromFactory.
SetThen(request, req, [&factory, func](uint64_t r, From value) {
911 func(std::move(value));
917template <
typename To>
923 fromFactory.
SetThen(request, req, [&factory, func](uint64_t r) {
934 fromFactory.
SetThen(request, req, [&factory, func](uint64_t r) {
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
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.
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
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