master
h 80 lines 1.85 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #pragma once
4
5 #include <optional>
6 #include <mutex>
7 #include <condition_variable>
8
9 /**
10 * @brief Class that contains a value T that can contain a single value and
11 * blocks until post or get can be satisfied.
12 *
13 * @tparam Value stored in this class.
14 */
15 template <typename T>
16 struct WaitableValue
17 {
18 public:
19 /**
20 * @brief Store value the value. Blocks until the value can be stored.
21 *
22 * @param[in] value Value to be stored.
23 */
24 void post(T& value)
25 {
26 std::unique_lock lck(m_mtx);
27 while (m_value.has_value())
28 {
29 m_cv.wait(lck);
30 }
31 m_value = value;
32 m_cv.notify_all();
33 }
34
35 /**
36 * @brief Retrieve the value. Blocks until a value is available.
37 *
38 * @return Value that was previously stored.
39 */
40 T get()
41 {
42 std::unique_lock lck(m_mtx);
43 while (!m_value.has_value())
44 {
45 m_cv.wait(lck);
46 }
47 auto return_value = m_value.value();
48 m_value.reset();
49 m_cv.notify_all();
50 return return_value;
51 }
52
53 /**
54 * @brief Attempt to retrieve the value with timeout.
55 *
56 * @param[in] timeout Duration to wait before returning empty.
57 * @return Either the value or a std::nullopt on timeout.
58 */
59 template <typename duration>
60 std::optional<T> try_get(duration timeout)
61 {
62 std::unique_lock lck(m_mtx);
63 while (!m_value.has_value())
64 {
65 if (m_cv.wait_for(lck, timeout) == std::cv_status::timeout)
66 {
67 return std::nullopt;
68 }
69 }
70 auto return_value = m_value.value();
71 m_value.reset();
72 m_cv.notify_all();
73 return {return_value};
74 }
75
76 private:
77 std::mutex m_mtx;
78 std::condition_variable m_cv;
79 std::optional<T> m_value;
80 };