Rename our allwpilib (which is now 2020) to not have 2019 in the name
Change-Id: I3c07f85ed32ab8b97db765a9b43f2a6ce7da964a
diff --git a/wpiutil/src/main/native/cpp/future.cpp b/wpiutil/src/main/native/cpp/future.cpp
new file mode 100644
index 0000000..7ce0875
--- /dev/null
+++ b/wpiutil/src/main/native/cpp/future.cpp
@@ -0,0 +1,119 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
+/* Open Source Software - may be modified and shared by FRC teams. The code */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project. */
+/*----------------------------------------------------------------------------*/
+
+#include "wpi/future.h"
+
+namespace wpi {
+namespace detail {
+
+PromiseFactoryBase::~PromiseFactoryBase() {
+ m_active = false;
+ m_resultCv.notify_all(); // wake up any waiters
+}
+
+void PromiseFactoryBase::IgnoreResult(uint64_t request) {
+ std::unique_lock lock(m_resultMutex);
+ EraseRequest(request);
+}
+
+uint64_t PromiseFactoryBase::CreateRequest() {
+ std::unique_lock lock(m_resultMutex);
+ uint64_t req = ++m_uid;
+ m_requests.push_back(req);
+ return req;
+}
+
+bool PromiseFactoryBase::EraseRequest(uint64_t request) {
+ if (request == 0) return false;
+ auto it = std::find_if(m_requests.begin(), m_requests.end(),
+ [=](auto r) { return r == request; });
+ if (it == m_requests.end()) return false; // no waiters
+ m_requests.erase(it);
+ return true;
+}
+
+} // namespace detail
+
+future<void> PromiseFactory<void>::MakeReadyFuture() {
+ std::unique_lock lock(GetResultMutex());
+ uint64_t req = CreateErasedRequest();
+ m_results.emplace_back(req);
+ return future<void>{this, req};
+}
+
+void PromiseFactory<void>::SetValue(uint64_t request) {
+ std::unique_lock lock(GetResultMutex());
+ if (!EraseRequest(request)) return;
+ auto it = std::find_if(m_thens.begin(), m_thens.end(),
+ [=](const auto& x) { return x.request == request; });
+ if (it != m_thens.end()) {
+ uint64_t outRequest = it->outRequest;
+ ThenFunction func = std::move(it->func);
+ m_thens.erase(it);
+ lock.unlock();
+ return func(outRequest);
+ }
+ m_results.emplace_back(request);
+ Notify();
+}
+
+void PromiseFactory<void>::SetThen(uint64_t request, uint64_t outRequest,
+ ThenFunction func) {
+ std::unique_lock lock(GetResultMutex());
+ auto it = std::find_if(m_results.begin(), m_results.end(),
+ [=](const auto& r) { return r == request; });
+ if (it != m_results.end()) {
+ m_results.erase(it);
+ lock.unlock();
+ return func(outRequest);
+ }
+ m_thens.emplace_back(request, outRequest, func);
+}
+
+bool PromiseFactory<void>::IsReady(uint64_t request) noexcept {
+ std::unique_lock lock(GetResultMutex());
+ auto it = std::find_if(m_results.begin(), m_results.end(),
+ [=](const auto& r) { return r == request; });
+ return it != m_results.end();
+}
+
+void PromiseFactory<void>::GetResult(uint64_t request) {
+ // wait for response
+ std::unique_lock lock(GetResultMutex());
+ while (IsActive()) {
+ // Did we get a response to *our* request?
+ auto it = std::find_if(m_results.begin(), m_results.end(),
+ [=](const auto& r) { return r == request; });
+ if (it != m_results.end()) {
+ // Yes, remove it from the vector and we're done.
+ m_results.erase(it);
+ return;
+ }
+ // No, keep waiting for a response
+ Wait(lock);
+ }
+}
+
+void PromiseFactory<void>::WaitResult(uint64_t request) {
+ // wait for response
+ std::unique_lock lock(GetResultMutex());
+ while (IsActive()) {
+ // Did we get a response to *our* request?
+ auto it = std::find_if(m_results.begin(), m_results.end(),
+ [=](const auto& r) { return r == request; });
+ if (it != m_results.end()) return;
+ // No, keep waiting for a response
+ Wait(lock);
+ }
+}
+
+PromiseFactory<void>& PromiseFactory<void>::GetInstance() {
+ static PromiseFactory<void> inst;
+ return inst;
+}
+
+} // namespace wpi