|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- /*!
- * \file cont/ring_iterator.h
- * \brief
- * A ring/circular iterator.
- *
- * \copyright Copyright (C) 2021 Christos Choutouridis <christos@choutouridis.net>
- *
- * <dl class=\"section copyright\"><dt>License</dt><dd>
- * The MIT License (MIT)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- * </dd></dl>
- */
-
- #ifndef TBX_CORE_RING_ITERATOR_H_
- #define TBX_CORE_RING_ITERATOR_H_
-
- #include <core/core.h>
-
- #include <iterator>
- #include <type_traits>
- #include <atomic>
-
- namespace tbx {
-
- template<typename Iter_t, size_t N, bool Atomic=false>
- class ring_iterator {
- //! \name STL iterator traits "forwarding"
- //! @{
- protected:
- using traits_type = std::iterator_traits<Iter_t>;
-
- public:
- using iterator_type = Iter_t;
- using iterator_category = typename traits_type::iterator_category;
- using value_type = typename traits_type::value_type;
- using difference_type = typename traits_type::difference_type;
- using reference = typename traits_type::reference;
- using pointer = typename traits_type::pointer;
- //! @}
-
-
- //! \name Constructor / Destructor
- //! @{
- public:
- constexpr ring_iterator(const Iter_t base =nullptr) noexcept :
- base_(base), iter_(base) { }
-
- constexpr ring_iterator(const Iter_t base, size_t elem) noexcept :
- base_(base), iter_(base + elem) { }
-
- constexpr ring_iterator(const ring_iterator& it) noexcept :
- base_(it.base_), iter_(it.iter_) { }
-
- constexpr ring_iterator& operator= (const ring_iterator& it) noexcept {
- base_ = it.base_;
- iter_ = it.iter_;
- return *this;
- }
- //! @}
-
- //! \name Forward iterator requirements
- //! @{
- public:
- constexpr reference operator*() const noexcept {
- return *iter_;
- }
-
- constexpr pointer operator->() const noexcept {
- return iter_;
- }
-
- constexpr ring_iterator& operator++() noexcept {
- if (static_cast<size_t>(++iter_ - base_) >= N)
- iter_ = base_;
- return *this;
- }
-
- constexpr ring_iterator operator++(int) noexcept {
- ring_iterator it = *this;
- if (static_cast<size_t>(++iter_ - base_) >= N)
- iter_ = base_;
- return it;
- }
- //! @}
-
- //! \name Bidirectional iterator requirements
- //! @{
- public:
- constexpr ring_iterator& operator--() noexcept {
- if (--iter_ < base_)
- iter_ = base_ + N -1;
- return *this;
- }
- constexpr ring_iterator operator--(int) noexcept {
- ring_iterator it = *this;
- if (--iter_ < base_)
- iter_ = base_ + N -1;
- return it;
- }
- //! @}
-
- //! \name Random access iterator requirements
- //! @{
- constexpr reference operator[](difference_type n) const noexcept {
- difference_type k = iter_ - base_; // ptrdiff from base_
- return (static_cast<size_t>(k + n) < N) ?
- base_[k + n] : // on range
- base_[k + n - N]; // out of range, loop
- }
- constexpr ring_iterator& operator+=(difference_type n) noexcept {
- difference_type k = iter_ - base_; // ptrdiff from base_
- iter_ += (static_cast<size_t>(k + n) < N) ?
- n : // on range
- n - N; // out of range, loop
- return *this;
- }
-
- constexpr ring_iterator operator+(difference_type n) const noexcept {
- difference_type k = iter_ - base_; // ptrdiff from base_
- return (static_cast<size_t>(k + n) < N) ?
- ring_iterator(base_, k + n) : // on range
- ring_iterator(base_, k + n - N); // out of range, loop
- }
- constexpr ring_iterator& operator-=(difference_type n) noexcept {
- difference_type k = iter_ - base_; // ptrdiff from base_
- iter_ -= ((k - n) < 0)?
- n - N: // out of range, loop
- n; // on range
- return *this;
- }
- constexpr ring_iterator operator-(difference_type n) const noexcept {
- difference_type k = iter_ - base_; // ptrdiff from base_
- return ((k - n) < 0) ?
- ring_iterator(base_, k - n + N) : // out of range, loop
- ring_iterator(base_, k - n); // on range
- }
- //! @}
-
- //! \name Data members and access
- //! @{
- constexpr const Iter_t& base() const noexcept {
- return base_;
- }
- constexpr const Iter_t& iter() const noexcept {
- return iter_;
- }
- constexpr size_t size() noexcept {
- return N;
- }
-
- constexpr operator Iter_t() noexcept { return iter_; }
- constexpr operator const Iter_t() const noexcept { return iter_; }
-
- protected:
- Iter_t base_;
- Iter_t iter_;
- //! @}
- };
-
- // Forward iterator requirements
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator==(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept {
- return lhs.iter() == rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator!=(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept {
- return lhs.iter() != rhs.iter();
- }
-
- // Random access iterator requirements
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator<(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept {
- return lhs.iter() < rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator<=(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept {
- return lhs.iter() <= rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator>(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept {
- return lhs.iter() > rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator>=(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept {
- return lhs.iter() >= rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline auto operator-(const ring_iterator<Iter_L, N>& lhs, const ring_iterator<Iter_R, N>& rhs)
- noexcept
- -> decltype(lhs.iter() - rhs.iter()) {
- auto diff = lhs.iter() - rhs.iter();
- return diff < 0 ?
- diff + N : // loop
- diff; // no loop
- }
-
- template<typename Iter, size_t N>
- inline ring_iterator<Iter, N> operator+(std::ptrdiff_t lhs, const ring_iterator<Iter, N>& rhs)
- noexcept {
- ring_iterator<Iter, N> it(rhs.iter());
- return it += lhs;
- }
-
-
-
-
-
-
- template<typename Iter_t, size_t N>
- class ring_iterator<Iter_t, N, true> {
- //! \name STL iterator traits "forwarding"
- //! @{
- protected:
- using traits_type = std::iterator_traits<Iter_t>;
-
- public:
- using iterator_type = Iter_t;
- using iterator_category = typename traits_type::iterator_category;
- using value_type = typename traits_type::value_type;
- using difference_type = typename traits_type::difference_type;
- using reference = typename traits_type::reference;
- using pointer = typename traits_type::pointer;
- //! @}
-
-
- //! \name Constructor / Destructor
- //! @{
- public:
- constexpr ring_iterator(const Iter_t base =nullptr) noexcept :
- base_(base), iter_(base) { }
-
- constexpr ring_iterator(const Iter_t base, size_t elem) noexcept :
- base_(base), iter_(base + elem) { }
-
- constexpr ring_iterator(const ring_iterator& it) noexcept :
- base_(it.base_) {
- iter_ = it.iter_.load(std::memory_order_acquire);
- }
-
- constexpr ring_iterator& operator= (const ring_iterator& it) noexcept {
- base_ = it.base_;
- iter_ = it.iter_.load(std::memory_order_acquire);
- return *this;
- }
- //! @}
-
- //! \name Forward iterator requirements
- //! @{
- public:
- constexpr reference operator*() const noexcept {
- return *iter_.load(std::memory_order_acquire);
- }
-
- constexpr pointer operator->() const noexcept {
- return iter_.load(std::memory_order_acquire);
- }
-
- constexpr ring_iterator& operator++() noexcept {
- Iter_t itnew, it = iter_.load(std::memory_order_acquire);
- do {
- itnew = it;
- if (static_cast<size_t>(++itnew - base_) >= N)
- itnew = base_;
- } while (!iter_.compare_exchange_weak(it, itnew, std::memory_order_acq_rel));
- return *this;
- }
- constexpr ring_iterator operator++(int) noexcept {
- ring_iterator ret = *this;
- Iter_t itnew, it = iter_.load(std::memory_order_acquire);
- do {
- itnew = it;
- if (static_cast<size_t>(++itnew - base_) >= N)
- itnew = base_;
- } while (!iter_.compare_exchange_weak(it, itnew, std::memory_order_acq_rel));
- return ret;
- }
- //! @}
-
- //! \name Bidirectional iterator requirements
- //! @{
- public:
- constexpr ring_iterator& operator--() noexcept {
- Iter_t itnew, it = iter_.load(std::memory_order_acquire);
- do {
- itnew = it;
- if (--itnew < base_)
- itnew = base_ + N -1;
- } while (!iter_.compare_exchange_weak(it, itnew, std::memory_order_acq_rel));
- return *this;
- }
- constexpr ring_iterator operator--(int) noexcept {
- ring_iterator ret = *this;
- Iter_t itnew, it = iter_.load(std::memory_order_acquire);
- do {
- itnew = it;
- if (--itnew < base_)
- itnew = base_ + N -1;
- } while (!iter_.compare_exchange_weak(it, itnew, std::memory_order_acq_rel));
- return ret;
- }
- //! @}
-
- //! \name Random access iterator requirements
- //! @{
- constexpr reference operator[](difference_type n) const noexcept {
- difference_type k = iter_.load(std::memory_order_acquire) - base_; // ptrdiff from base_
- return (static_cast<size_t>(k + n) < N) ?
- base_[k + n] : // on range
- base_[k + n - N]; // out of range, loop
- }
- constexpr ring_iterator& operator+=(difference_type n) noexcept {
- Iter_t itnew, it = iter_.load(std::memory_order_acquire);
- do {
- itnew = it;
- difference_type k = it - base_; // ptrdiff from base_
- itnew += (static_cast<size_t>(k + n) < N) ?
- n : // on range
- n - N; // out of range, loop
- } while (!iter_.compare_exchange_weak(it, itnew, std::memory_order_acquire));
- return *this;
- }
- constexpr ring_iterator operator+(difference_type n) const noexcept {
- difference_type k = iter_.load(std::memory_order_acquire) - base_; // ptrdiff from base_
- return (static_cast<size_t>(k + n) < N) ?
- ring_iterator(base_, k + n) : // on range
- ring_iterator(base_, k + n - N); // out of range, loop
- }
- constexpr ring_iterator& operator-=(difference_type n) noexcept {
- Iter_t itnew, it = iter_.load(std::memory_order_acquire);
- do {
- itnew = it;
- difference_type k = it - base_; // ptrdiff from base_
- itnew -= ((k - n) < 0)?
- n - N: // out of range, loop
- n; // on range
- } while (!iter_.compare_exchange_weak(it, itnew, std::memory_order_acquire));
- return *this;
- }
- constexpr ring_iterator operator-(difference_type n) const noexcept {
- difference_type k = iter_.load(std::memory_order_acquire) - base_; // ptrdiff from base_
- return ((k - n) < 0) ?
- ring_iterator(base_, k - n + N) : // out of range, loop
- ring_iterator(base_, k - n); // on range
- }
- //! @}
-
- //! \name Data members and access
- //! @{
- constexpr const Iter_t& base() const noexcept {
- return base_;
- }
- constexpr const Iter_t iter() const noexcept {
- return iter_.load(std::memory_order_acquire);
- }
- constexpr size_t size() noexcept {
- return N;
- }
-
- constexpr operator Iter_t() noexcept { return iter_.load(std::memory_order_acquire); }
- constexpr operator const Iter_t() const noexcept { return iter_.load(std::memory_order_acquire); }
-
- protected:
- Iter_t base_;
- std::atomic<Iter_t> iter_;
- //! @}
- };
-
- // Forward iterator requirements
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator==(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept {
- return lhs.iter() == rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator!=(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept {
- return lhs.iter() != rhs.iter();
- }
-
- // Random access iterator requirements
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator<(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept {
- return lhs.iter() < rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator<=(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept {
- return lhs.iter() <= rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator>(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept {
- return lhs.iter() > rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline bool operator>=(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept {
- return lhs.iter() >= rhs.iter();
- }
-
- template<typename Iter_L, typename Iter_R, size_t N>
- inline auto operator-(const ring_iterator<Iter_L, N, true>& lhs, const ring_iterator<Iter_R, N, true>& rhs)
- noexcept
- -> decltype(lhs.iter() - rhs.iter()) {
- auto diff = lhs.iter() - rhs.iter();
- return diff < 0 ?
- diff + N : // loop
- diff; // no loop
- }
-
- template<typename Iter, size_t N>
- inline ring_iterator<Iter, N, true> operator+(std::ptrdiff_t lhs, const ring_iterator<Iter, N, true>& rhs)
- noexcept {
- ring_iterator<Iter, N, true> it(rhs.iter());
- return it += lhs;
- }
-
- } //namespace tbx;
-
- #endif /* TBX_CORE_RING_ITERATOR_H_ */
|