55#include < cassert>
66#include < condition_variable>
77#include < cstddef>
8+ #include < iterator>
89#include < mutex>
910#include < optional>
10- #include < iterator>
1111#include < type_traits>
1212#include < utility>
1313
1414namespace dice ::template_library {
1515
16- /* *
16+ /* *
1717 * A multi producer, multi consumer channel
1818 * that only retains the last sent value.
1919 */
@@ -28,11 +28,11 @@ namespace dice::template_library {
2828 using const_pointer = T const *;
2929
3030 private:
31- std::mutex value_mutex_; // /< mutex for value_
32- std::optional<T> value_; // /< the last value that was sent
31+ std::mutex value_mutex_; // /< mutex for value_
32+ std::optional<T> value_; // /< the last value that was sent
3333
34- std::atomic_flag closed_ = ATOMIC_FLAG_INIT ; // /< true if this channel is closed
35- std::condition_variable has_value_; // /< condvar for value_.has_value()
34+ std::atomic_flag closed_ = ATOMIC_FLAG_INIT ; // /< true if this channel is closed
35+ std::condition_variable has_value_; // /< condvar for value_.has_value()
3636
3737 public:
3838 exchange_channel () = default ;
@@ -45,7 +45,7 @@ namespace dice::template_library {
4545
4646 ~exchange_channel () noexcept = default ;
4747
48- /* *
48+ /* *
4949 * Close the channel.
5050 * After calling close calls to push() will return false
5151 * and calls to try_pop will return std::nullopt once the already present elements are exhausted
@@ -59,23 +59,23 @@ namespace dice::template_library {
5959 std::lock_guard lock{value_mutex_};
6060 closed_.test_and_set (std::memory_order_release);
6161 }
62- has_value_.notify_all (); // notify pop() so that it does not get stuck
62+ has_value_.notify_all (); // notify pop() so that it does not get stuck
6363 }
6464
65- /* *
65+ /* *
6666 * @return true if this channel is closed
6767 */
6868 [[nodiscard]] bool closed () const noexcept {
6969 return closed_.test (std::memory_order_acquire);
7070 }
7171
72- /* *
72+ /* *
7373 * Emplace an element into the channel, replaces the current element in the channel if there is one.
7474 *
7575 * @param args constructor args
7676 * @return true if emplacing the element succeeded because the channel is not yet closed
7777 */
78- template <typename ...Args>
78+ template <typename ... Args>
7979 bool emplace (Args &&...args) noexcept (std::is_nothrow_constructible_v<value_type, decltype (std::forward<Args>(args))...>) {
8080 if (closed_.test (std::memory_order_acquire)) [[unlikely]] {
8181 return false ;
@@ -95,7 +95,7 @@ namespace dice::template_library {
9595 return true ;
9696 }
9797
98- /* *
98+ /* *
9999 * Push a single element into the channel, replaces the current element in the channel if there is one.
100100 *
101101 * @param value the element to push
@@ -115,15 +115,17 @@ namespace dice::template_library {
115115 return emplace (std::move (value));
116116 }
117117
118- /* *
118+ /* *
119119 * Try to get a (previously pushed) element from the channel.
120120 * If there is no element available, blocks until there is one available or the channel is closed.
121121 *
122122 * @return std::nullopt if the channel was closed, an element otherwise
123123 */
124124 [[nodiscard]] std::optional<value_type> pop () noexcept (std::is_nothrow_move_constructible_v<value_type>) {
125125 std::unique_lock lock{value_mutex_};
126- has_value_.wait (lock, [this ]() noexcept { return value_.has_value () || closed_.test (std::memory_order_relaxed); });
126+ has_value_.wait (lock, [this ]() noexcept {
127+ return value_.has_value () || closed_.test (std::memory_order_relaxed);
128+ });
127129
128130 if (!value_.has_value ()) [[unlikely]] {
129131 // implies closed_ == true
@@ -158,14 +160,15 @@ namespace dice::template_library {
158160
159161 private:
160162 exchange_channel *chan_;
161- mutable std::optional<value_type> buf_; // /< this has to be mutable for this iterator to fullfill std::input_iterator
163+ mutable std::optional<value_type> buf_; // /< this has to be mutable for this iterator to fullfill std::input_iterator
162164
163165 void advance () noexcept (std::is_nothrow_move_constructible_v<value_type>) {
164166 buf_ = chan_->pop ();
165167 }
166168
167169 public:
168- explicit iterator (channel_type *chan) noexcept (std::is_nothrow_move_constructible_v<value_type>) : chan_{chan} {
170+ explicit iterator (channel_type *chan) noexcept (std::is_nothrow_move_constructible_v<value_type>)
171+ : chan_{chan} {
169172 advance ();
170173 }
171174
@@ -230,7 +233,7 @@ namespace dice::template_library {
230233
231234 using sentinel = std::default_sentinel_t ;
232235
233- /* *
236+ /* *
234237 * @return an iterator over all present and future elements of this channel
235238 * @note iterator == end() is true once the channel is closed
236239 */
@@ -243,6 +246,6 @@ namespace dice::template_library {
243246 }
244247 };
245248
246- } // namespace dice::template_library
249+ } // namespace dice::template_library
247250
248- #endif // DICE_TEMPLATELIBRARY_EXCHANGECHANNEL_HPP
251+ #endif // DICE_TEMPLATELIBRARY_EXCHANGECHANNEL_HPP
0 commit comments