Path: blob/master/Utilities/cmcppdap/include/dap/future.h
3158 views
// Copyright 2019 Google LLC1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// https://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314#ifndef dap_future_h15#define dap_future_h1617#include <condition_variable>18#include <memory>19#include <mutex>2021namespace dap {2223// internal functionality24namespace detail {25template <typename T>26struct promise_state {27T val;28std::mutex mutex;29std::condition_variable cv;30bool hasVal = false;31};32} // namespace detail3334// forward declaration35template <typename T>36class promise;3738// future_status is the enumeration returned by future::wait_for and39// future::wait_until.40enum class future_status {41ready,42timeout,43};4445// future is a minimal reimplementation of std::future, that does not suffer46// from TSAN false positives. See:47// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=6920448template <typename T>49class future {50public:51using State = detail::promise_state<T>;5253// constructors54inline future() = default;55inline future(future&&) = default;5657// valid() returns true if the future has an internal state.58bool valid() const;5960// get() blocks until the future has a valid result, and returns it.61// The future must have a valid internal state to call this method.62inline T get();6364// wait() blocks until the future has a valid result.65// The future must have a valid internal state to call this method.66void wait() const;6768// wait_for() blocks until the future has a valid result, or the timeout is69// reached.70// The future must have a valid internal state to call this method.71template <class Rep, class Period>72future_status wait_for(73const std::chrono::duration<Rep, Period>& timeout) const;7475// wait_until() blocks until the future has a valid result, or the timeout is76// reached.77// The future must have a valid internal state to call this method.78template <class Clock, class Duration>79future_status wait_until(80const std::chrono::time_point<Clock, Duration>& timeout) const;8182private:83friend promise<T>;84future(const future&) = delete;85inline future(const std::shared_ptr<State>& state);8687std::shared_ptr<State> state = std::make_shared<State>();88};8990template <typename T>91future<T>::future(const std::shared_ptr<State>& s) : state(s) {}9293template <typename T>94bool future<T>::valid() const {95return static_cast<bool>(state);96}9798template <typename T>99T future<T>::get() {100std::unique_lock<std::mutex> lock(state->mutex);101state->cv.wait(lock, [&] { return state->hasVal; });102return state->val;103}104105template <typename T>106void future<T>::wait() const {107std::unique_lock<std::mutex> lock(state->mutex);108state->cv.wait(lock, [&] { return state->hasVal; });109}110111template <typename T>112template <class Rep, class Period>113future_status future<T>::wait_for(114const std::chrono::duration<Rep, Period>& timeout) const {115std::unique_lock<std::mutex> lock(state->mutex);116return state->cv.wait_for(lock, timeout, [&] { return state->hasVal; })117? future_status::ready118: future_status::timeout;119}120121template <typename T>122template <class Clock, class Duration>123future_status future<T>::wait_until(124const std::chrono::time_point<Clock, Duration>& timeout) const {125std::unique_lock<std::mutex> lock(state->mutex);126return state->cv.wait_until(lock, timeout, [&] { return state->hasVal; })127? future_status::ready128: future_status::timeout;129}130131// promise is a minimal reimplementation of std::promise, that does not suffer132// from TSAN false positives. See:133// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69204134template <typename T>135class promise {136public:137// constructors138inline promise() = default;139inline promise(promise&& other) = default;140inline promise(const promise& other) = default;141142// set_value() stores value to the shared state.143// set_value() must only be called once.144inline void set_value(const T& value) const;145inline void set_value(T&& value) const;146147// get_future() returns a future sharing this promise's state.148future<T> get_future();149150private:151using State = detail::promise_state<T>;152std::shared_ptr<State> state = std::make_shared<State>();153};154155template <typename T>156future<T> promise<T>::get_future() {157return future<T>(state);158}159160template <typename T>161void promise<T>::set_value(const T& value) const {162std::unique_lock<std::mutex> lock(state->mutex);163state->val = value;164state->hasVal = true;165state->cv.notify_all();166}167168template <typename T>169void promise<T>::set_value(T&& value) const {170std::unique_lock<std::mutex> lock(state->mutex);171state->val = std::move(value);172state->hasVal = true;173state->cv.notify_all();174}175176} // namespace dap177178#endif // dap_future_h179180181