// Copyright (C) 2022 Andrei Avram #ifndef MSD_CHANNEL_BLOCKING_ITERATOR_HPP_ #define MSD_CHANNEL_BLOCKING_ITERATOR_HPP_ #include #include namespace msd { /** * @brief An iterator that block the current thread, * waiting to fetch elements from the channel. * * Used to implement channel range-based for loop. * * @tparam Channel Instance of channel. */ template class blocking_iterator { public: using value_type = typename channel::value_type; explicit blocking_iterator(channel& ch) : ch_{ch} {} /** * Advances to next element in the channel. */ blocking_iterator operator++() const noexcept { return *this; } /** * Returns an element from the channel. */ value_type operator*() const { value_type value; value << ch_; return value; } /** * Makes iteration continue until the channel is closed and empty. */ bool operator!=(blocking_iterator) const { std::unique_lock lock{ch_.mtx_}; ch_.waitBeforeRead(lock); return !(ch_.closed() && ch_.empty()); } private: channel& ch_; }; } // namespace msd /** * @brief Output iterator specialization */ template struct std::iterator_traits> { using value_type = typename msd::blocking_iterator::value_type; using iterator_category = std::output_iterator_tag; }; #endif // MSD_CHANNEL_BLOCKING_ITERATOR_HPP_