blob: 7ce0875a11cf770476fc1907b5220e888cb51f92 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -08002/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
Brian Silverman41cdd3e2019-01-19 19:48:58 -08003/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "wpi/future.h"
9
10namespace wpi {
11namespace detail {
12
13PromiseFactoryBase::~PromiseFactoryBase() {
14 m_active = false;
15 m_resultCv.notify_all(); // wake up any waiters
16}
17
18void PromiseFactoryBase::IgnoreResult(uint64_t request) {
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080019 std::unique_lock lock(m_resultMutex);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080020 EraseRequest(request);
21}
22
23uint64_t PromiseFactoryBase::CreateRequest() {
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080024 std::unique_lock lock(m_resultMutex);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080025 uint64_t req = ++m_uid;
26 m_requests.push_back(req);
27 return req;
28}
29
30bool PromiseFactoryBase::EraseRequest(uint64_t request) {
31 if (request == 0) return false;
32 auto it = std::find_if(m_requests.begin(), m_requests.end(),
33 [=](auto r) { return r == request; });
34 if (it == m_requests.end()) return false; // no waiters
35 m_requests.erase(it);
36 return true;
37}
38
39} // namespace detail
40
41future<void> PromiseFactory<void>::MakeReadyFuture() {
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080042 std::unique_lock lock(GetResultMutex());
Brian Silverman41cdd3e2019-01-19 19:48:58 -080043 uint64_t req = CreateErasedRequest();
44 m_results.emplace_back(req);
45 return future<void>{this, req};
46}
47
48void PromiseFactory<void>::SetValue(uint64_t request) {
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080049 std::unique_lock lock(GetResultMutex());
Brian Silverman41cdd3e2019-01-19 19:48:58 -080050 if (!EraseRequest(request)) return;
51 auto it = std::find_if(m_thens.begin(), m_thens.end(),
52 [=](const auto& x) { return x.request == request; });
53 if (it != m_thens.end()) {
54 uint64_t outRequest = it->outRequest;
55 ThenFunction func = std::move(it->func);
56 m_thens.erase(it);
57 lock.unlock();
58 return func(outRequest);
59 }
60 m_results.emplace_back(request);
61 Notify();
62}
63
64void PromiseFactory<void>::SetThen(uint64_t request, uint64_t outRequest,
65 ThenFunction func) {
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080066 std::unique_lock lock(GetResultMutex());
Brian Silverman41cdd3e2019-01-19 19:48:58 -080067 auto it = std::find_if(m_results.begin(), m_results.end(),
68 [=](const auto& r) { return r == request; });
69 if (it != m_results.end()) {
70 m_results.erase(it);
71 lock.unlock();
72 return func(outRequest);
73 }
74 m_thens.emplace_back(request, outRequest, func);
75}
76
77bool PromiseFactory<void>::IsReady(uint64_t request) noexcept {
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080078 std::unique_lock lock(GetResultMutex());
Brian Silverman41cdd3e2019-01-19 19:48:58 -080079 auto it = std::find_if(m_results.begin(), m_results.end(),
80 [=](const auto& r) { return r == request; });
81 return it != m_results.end();
82}
83
84void PromiseFactory<void>::GetResult(uint64_t request) {
85 // wait for response
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080086 std::unique_lock lock(GetResultMutex());
Brian Silverman41cdd3e2019-01-19 19:48:58 -080087 while (IsActive()) {
88 // Did we get a response to *our* request?
89 auto it = std::find_if(m_results.begin(), m_results.end(),
90 [=](const auto& r) { return r == request; });
91 if (it != m_results.end()) {
92 // Yes, remove it from the vector and we're done.
93 m_results.erase(it);
94 return;
95 }
96 // No, keep waiting for a response
97 Wait(lock);
98 }
99}
100
101void PromiseFactory<void>::WaitResult(uint64_t request) {
102 // wait for response
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -0800103 std::unique_lock lock(GetResultMutex());
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800104 while (IsActive()) {
105 // Did we get a response to *our* request?
106 auto it = std::find_if(m_results.begin(), m_results.end(),
107 [=](const auto& r) { return r == request; });
108 if (it != m_results.end()) return;
109 // No, keep waiting for a response
110 Wait(lock);
111 }
112}
113
114PromiseFactory<void>& PromiseFactory<void>::GetInstance() {
115 static PromiseFactory<void> inst;
116 return inst;
117}
118
119} // namespace wpi