aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/jau/cow_darray.hpp4
-rw-r--r--include/jau/cow_iterator.hpp269
-rw-r--r--include/jau/cow_vector.hpp4
3 files changed, 237 insertions, 40 deletions
diff --git a/include/jau/cow_darray.hpp b/include/jau/cow_darray.hpp
index 05d925d..64c1e89 100644
--- a/include/jau/cow_darray.hpp
+++ b/include/jau/cow_darray.hpp
@@ -128,7 +128,7 @@ namespace jau {
* Using jau::cow_darray::get_snapshot() at construction.
* </p>
*/
- typedef cow_ro_iterator<value_type, storage_t, storage_ref_t, size_type> const_iterator;
+ typedef cow_ro_iterator<storage_t, storage_ref_t> const_iterator;
/**
* Mutable, read-write iterator, holding the write-lock and a store copy until destruction.
@@ -137,7 +137,7 @@ namespace jau {
* and jau::cow_darray::set_store() at destruction.
* </p>
*/
- typedef cow_rw_iterator<value_type, storage_t, storage_ref_t, cow_darray, size_type> iterator;
+ typedef cow_rw_iterator<storage_t, storage_ref_t, cow_darray> iterator;
// typedef std::reverse_iterator<iterator> reverse_iterator;
// typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
diff --git a/include/jau/cow_iterator.hpp b/include/jau/cow_iterator.hpp
index 5775a24..938edcc 100644
--- a/include/jau/cow_iterator.hpp
+++ b/include/jau/cow_iterator.hpp
@@ -29,33 +29,92 @@
#include <limits>
#include <mutex>
+#include <type_traits>
+
namespace jau {
/**
- * Implementation of a Copy-On-Write (CoW) read-only iterator for immutable Value_type,
- * holding the shared Value_type& of the current CoW storage until destruction.
+ * Implementation of a Copy-On-Write (CoW) read-only iterator for immutable value_type.<br>
+ * Instance holds the 'shared value_type reference', Storage_ref_type,
+ * of the current CoW storage until destruction.
+ * <p>
+ * This iterator simply wraps the native iterator of type 'iterator_type'
+ * and manages the CoW related resource lifecycle.
+ * </p>
+ * <p>
+ * Implementation complies with iterator_category 'random_access_iterator_tag'
+ * </p>
*/
- template <typename Value_type, typename Storage_type, typename Storage_ref_type, typename Size_type>
+ template <typename Storage_type, typename Storage_ref_type>
class cow_ro_iterator {
+ public:
+ /** Actual const iterator type of the contained native iterator, probably a simple pointer. */
+ typedef typename Storage_type::const_iterator iterator_type;
private:
+ typedef std::iterator_traits<iterator_type> sub_traits_t;
+
Storage_ref_type store_holder_;
- typename Storage_type::const_iterator iterator_;
+ iterator_type iterator_;
public:
- typedef Size_type size_type;
- typedef typename std::make_signed<Size_type>::type difference_type;
+ typedef typename sub_traits_t::iterator_category iterator_category; // random_access_iterator_tag
+
+ typedef typename Storage_type::size_type size_type; // using our template overload Size_type
+ typedef typename Storage_type::difference_type difference_type; // derived from our Size_type
+ // typedef typename Storage_type::value_type value_type; // OK
+ // typedef typename Storage_type::reference reference; // for some reason, the 'const' is lost
+ // typedef typename Storage_type::pointer pointer; // for some reason, the 'const' is lost
+ typedef typename sub_traits_t::value_type value_type; // OK
+ typedef typename sub_traits_t::reference reference; // 'const value_type &'
+ typedef typename sub_traits_t::pointer pointer; // 'const value_type *'
+
+#if 0
+// TODO ???
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ using iterator_concept = std::__detail::__iter_concept<_Iterator>;
+#endif
+#endif
- constexpr cow_ro_iterator(Storage_ref_type store, typename Storage_type::const_iterator iter)
- : store_holder_(store), iterator_(iter) {}
+ public:
+ constexpr cow_ro_iterator(Storage_ref_type store, iterator_type iter)
+ : store_holder_(store), iterator_(iter) { }
- constexpr explicit cow_ro_iterator(const cow_ro_iterator& o) noexcept
+ // C++ named requirements: LegacyIterator: CopyConstructible
+ constexpr cow_ro_iterator(const cow_ro_iterator& o) noexcept
: store_holder_(o.store_holder_), iterator_(o.iterator_) {}
+ // C++ named requirements: LegacyIterator: CopyAssignable
+ constexpr cow_ro_iterator& operator=(const cow_ro_iterator& o) noexcept {
+ store_holder_ = o.store_holder_;
+ iterator_ = o.iterator_;
+ }
+
+ // C++ named requirements: LegacyIterator: MoveConstructable
+ constexpr cow_ro_iterator(cow_ro_iterator && o) noexcept
+ : store_holder_(std::move(o.store_holder_)), iterator_(std::move(o.iterator_)) {
+ o.store_holder_ = nullptr;
+ // o.iterator_ = nullptr;
+ }
+
+ // C++ named requirements: LegacyIterator: MoveAssignable
+ constexpr cow_ro_iterator& operator=(cow_ro_iterator&& o) noexcept {
+ store_holder_ = std::move(o.store_holder_);
+ iterator_ = std::move(o.iterator_);
+ o.store_holder_ = nullptr;
+ // o.iterator_ = nullptr;
+ }
+
+ // C++ named requirements: LegacyIterator: Swappable
+ void swap(cow_ro_iterator& o) noexcept {
+ std::swap( store_holder_, o.store_holder_);
+ std::swap( iterator_, o.iterator_);
+ }
+
/**
* Returns a copy of the underlying storage const_iterator.
*/
- typename Storage_type::const_iterator underling() const noexcept { return iterator_; };
+ iterator_type underling() const noexcept { return iterator_; };
// Multipass guarantee equality
@@ -70,12 +129,43 @@ namespace jau {
constexpr bool operator!=(const cow_ro_iterator& rhs) const noexcept
{ return !(*this == rhs); }
+ // Relation
+
+ constexpr bool operator<=(const cow_ro_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return true;
+ }
+ return store_holder_ == rhs.store_holder_ &&
+ iterator_ <= rhs.iterator_;
+ }
+ constexpr bool operator<(const cow_ro_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return false;
+ }
+ return store_holder_ == rhs.store_holder_ &&
+ iterator_ < rhs.iterator_;
+ }
+ constexpr bool operator>=(const cow_ro_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return true;
+ }
+ return store_holder_ == rhs.store_holder_ &&
+ iterator_ >= rhs.iterator_;
+ }
+ constexpr bool operator>(const cow_ro_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return false;
+ }
+ return store_holder_ == rhs.store_holder_ &&
+ iterator_ > rhs.iterator_;
+ }
+
// Forward iterator requirements
- constexpr const Value_type& operator*() const noexcept
+ constexpr const reference operator*() const noexcept
{ return *iterator_; }
- constexpr const Value_type* operator->() const noexcept
+ constexpr const pointer operator->() const noexcept
{ return iterator_; }
/** Pre-increment; Well performing, return *this. */
@@ -85,7 +175,7 @@ namespace jau {
}
/** Post-increment; Try to avoid: Low performance due to returning copy-ctor. */
- constexpr cow_ro_iterator& operator++(int) noexcept
+ constexpr cow_ro_iterator operator++(int) noexcept
{ return cow_ro_iterator(store_holder_, iterator_++); }
// Bidirectional iterator requirements
@@ -97,13 +187,13 @@ namespace jau {
}
/** Post-decrement; Try to avoid: Low performance due to returning copy-ctor. */
- constexpr cow_ro_iterator& operator--(int) noexcept
- { return cow_iterator(store_holder_, iterator_--); }
+ constexpr cow_ro_iterator operator--(int) noexcept
+ { return cow_ro_iterator(store_holder_, iterator_--); }
// Random access iterator requirements
/** Subscript of 'element_index', returning immutable Value_type reference. */
- constexpr const Value_type& operator[](difference_type i) const noexcept
+ constexpr const reference operator[](difference_type i) const noexcept
{ return iterator_[i]; }
/** Addition-assignment of 'element_count'; Well performing, return *this. */
@@ -112,7 +202,7 @@ namespace jau {
/** Binary 'iterator + element_count'; Try to avoid: Low performance due to returning copy-ctor. */
constexpr cow_ro_iterator operator+(difference_type rhs) const noexcept
- { return cow_iterator(store_holder_, iterator_ + rhs); }
+ { return cow_ro_iterator(store_holder_, iterator_ + rhs); }
/** Subtraction-assignment of 'element_count'; Well performing, return *this. */
constexpr cow_ro_iterator& operator-=(difference_type i) noexcept
@@ -120,7 +210,7 @@ namespace jau {
/** Binary 'iterator - element_count'; Try to avoid: Low performance due to returning copy-ctor. */
constexpr cow_ro_iterator operator-(difference_type rhs) const noexcept
- { return cow_iterator(store_holder_, iterator_ - rhs); }
+ { return cow_ro_iterator(store_holder_, iterator_ - rhs); }
// Distance or element count, binary subtraction of two iterator.
@@ -130,31 +220,63 @@ namespace jau {
};
/**
- * Implementation of a Copy-On-Write (CoW) read-write iterator for mutable Value_type,
- * holding the write lock, a new copy of the CoW storage and a Value_type& of the CoW container itself.
+ * Implementation of a Copy-On-Write (CoW) read-write iterator for mutable value_type.<br>
+ * Instance holds the 'shared value_type reference', Storage_ref_type,
+ * of the current CoW storage until destruction.
+ * <p>
+ * This iterator simply wraps the native iterator of type 'iterator_type'
+ * and manages the CoW related resource lifecycle.
+ * </p>
* <p>
* At destruction, the mutated local storage will replace the
* storage in the CoW container and the lock will be released.
* </p>
*/
- template <typename Value_type, typename Storage_type, typename Storage_ref_type, typename CoW_container, typename Size_type>
+ template <typename Storage_type, typename Storage_ref_type, typename CoW_container>
class cow_rw_iterator {
+ public:
+ /** Actual iterator type of the contained native iterator, probably a simple pointer. */
+ typedef typename Storage_type::iterator iterator_type;
private:
+ typedef std::iterator_traits<iterator_type> sub_traits_t;
+
CoW_container& cow_parent_;
- const std::lock_guard<std::recursive_mutex> lock_;
+ std::lock_guard<std::recursive_mutex> lock_;
Storage_ref_type new_store_;
- typename Storage_type::iterator iterator_;
+ iterator_type iterator_;
- constexpr explicit cow_rw_iterator(CoW_container& cow_parent, Storage_ref_type& store, typename Storage_type::iterator iter) noexcept
+ constexpr explicit cow_rw_iterator(CoW_container& cow_parent, Storage_ref_type& store, iterator_type iter) noexcept
: cow_parent_(cow_parent), lock_(cow_parent.get_write_mutex()), new_store_(store), iterator_(iter) {}
public:
- typedef Size_type size_type;
- typedef typename std::make_signed<Size_type>::type difference_type;
+ typedef typename sub_traits_t::iterator_category iterator_category; // random_access_iterator_tag
+
+ typedef typename Storage_type::size_type size_type; // using our template overload Size_type
+ typedef typename Storage_type::difference_type difference_type; // derived from our Size_type
+ // typedef typename Storage_type::value_type value_type; // OK
+ // typedef typename Storage_type::reference reference; //
+ // typedef typename Storage_type::pointer pointer; //
+ typedef typename sub_traits_t::value_type value_type; // OK
+ typedef typename sub_traits_t::reference reference; // 'value_type &'
+ typedef typename sub_traits_t::pointer pointer; // 'value_type *'
+
+ #if 0
+ // TODO ???
+ #if __cplusplus > 201703L && __cpp_lib_concepts
+ using iterator_concept = std::__detail::__iter_concept<_Iterator>;
+ #endif
+ #endif
+
+ public:
- constexpr cow_rw_iterator(CoW_container& cow_parent, typename Storage_type::iterator (*get_iterator)(Storage_ref_type&))
- : cow_parent_(cow_parent), lock_(cow_parent.get_write_mutex()), new_store_(cow_parent.copy_store()), iterator_(get_iterator(new_store_)) {}
+ constexpr cow_rw_iterator(CoW_container& cow_parent, iterator_type (*get_iterator)(Storage_ref_type&))
+ : cow_parent_(cow_parent), lock_(cow_parent.get_write_mutex()),
+ new_store_(cow_parent.copy_store()), iterator_(get_iterator(new_store_)) {}
+
+ constexpr cow_rw_iterator(CoW_container& cow_parent, iterator_type iter)
+ : cow_parent_(cow_parent), lock_(cow_parent.get_write_mutex()),
+ new_store_(cow_parent.copy_store()), iterator_(iter) {}
#if __cplusplus > 201703L
constexpr ~cow_rw_iterator() noexcept
@@ -165,6 +287,46 @@ namespace jau {
cow_parent_.set_store(std::move(new_store_));
}
+ // C++ named requirements: LegacyIterator: CopyConstructible
+ constexpr cow_rw_iterator(const cow_rw_iterator& o) noexcept
+ : cow_parent_(o.cow_parent_), lock_(cow_parent_.get_write_mutex()),
+ new_store_(o.new_store_), iterator_(o.iterator_) {}
+
+ // C++ named requirements: LegacyIterator: CopyAssignable
+ constexpr cow_rw_iterator& operator=(const cow_rw_iterator& o) noexcept {
+ cow_parent_ = o.cow_parent_;
+ lock_ = cow_parent_.get_write_mutex();
+ new_store_ = o.new_store_;
+ iterator_ = o.iterator_;
+ }
+
+ // C++ named requirements: LegacyIterator: MoveConstructable
+ constexpr cow_rw_iterator(cow_rw_iterator && o) noexcept
+ : cow_parent_(std::move(o.cow_parent_)), lock_(cow_parent_.get_write_mutex()),
+ new_store_(std::move(o.new_store_)), iterator_(std::move(o.iterator_)) {
+ o.lock_ = nullptr; // ???
+ o.new_store_ = nullptr;
+ // o.iterator_ = nullptr;
+ }
+
+ // C++ named requirements: LegacyIterator: MoveAssignable
+ constexpr cow_rw_iterator& operator=(cow_rw_iterator&& o) noexcept {
+ cow_parent_ = std::move(o.cow_parent_);
+ lock_ = cow_parent_.get_write_mutex();
+ new_store_ = std::move(o.new_store_);
+ iterator_ = std::move(o.iterator_);
+ o.new_store_ = nullptr;
+ // o.iterator_ = nullptr;
+ }
+
+ // C++ named requirements: LegacyIterator: Swappable
+ void swap(cow_rw_iterator& o) noexcept {
+ std::swap( cow_parent_, o.cow_parent_);
+ // std::swap( lock_, o.lock_); // lock stays in each
+ std::swap( new_store_, o.new_store_);
+ std::swap( iterator_, o.iterator_);
+ }
+
/**
* Returns a copy of the underlying storage iterator.
*/
@@ -184,18 +346,53 @@ namespace jau {
constexpr bool operator!=(const cow_rw_iterator& rhs) const noexcept
{ return !(*this == rhs); }
+ // Relation
+
+ constexpr bool operator<=(const cow_rw_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return true;
+ }
+ return &cow_parent_ == &rhs.cow_parent_ &&
+ new_store_ == rhs.new_store_ &&
+ iterator_ <= rhs.iterator_;
+ }
+ constexpr bool operator<(const cow_rw_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return false;
+ }
+ return &cow_parent_ == &rhs.cow_parent_ &&
+ new_store_ == rhs.new_store_ &&
+ iterator_ < rhs.iterator_;
+ }
+ constexpr bool operator>=(const cow_rw_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return true;
+ }
+ return &cow_parent_ == &rhs.cow_parent_ &&
+ new_store_ == rhs.new_store_ &&
+ iterator_ >= rhs.iterator_;
+ }
+ constexpr bool operator>(const cow_rw_iterator& rhs) const noexcept {
+ if( this == &rhs ) {
+ return false;
+ }
+ return &cow_parent_ == &rhs.cow_parent_ &&
+ new_store_ == rhs.new_store_ &&
+ iterator_ > rhs.iterator_;
+ }
+
// Forward iterator requirements
- constexpr const Value_type& operator*() const noexcept
+ constexpr const reference operator*() const noexcept
{ return *iterator_; }
- constexpr const Value_type* operator->() const noexcept
+ constexpr const pointer operator->() const noexcept
{ return iterator_; }
- constexpr Value_type& operator*() noexcept
+ constexpr reference operator*() noexcept
{ return *iterator_; }
- constexpr Value_type* operator->() noexcept
+ constexpr pointer operator->() noexcept
{ return iterator_; }
/** Pre-increment; Well performing, return *this. */
@@ -205,7 +402,7 @@ namespace jau {
}
/** Post-increment; Try to avoid: Low performance due to returning copy-ctor. */
- constexpr cow_rw_iterator& operator++(int) noexcept
+ constexpr cow_rw_iterator operator++(int) noexcept
{ return cow_rw_iterator(cow_parent_, new_store_, iterator_++); }
// Bidirectional iterator requirements
@@ -217,17 +414,17 @@ namespace jau {
}
/** Post-decrement; Try to avoid: Low performance due to returning copy-ctor. */
- constexpr cow_rw_iterator& operator--(int) noexcept
+ constexpr cow_rw_iterator operator--(int) noexcept
{ return cow_rw_iterator(cow_parent_, new_store_, iterator_--); }
// Random access iterator requirements
/** Subscript of 'element_index', returning immutable Value_type reference. */
- constexpr const Value_type& operator[](difference_type i) const noexcept
+ constexpr const reference operator[](difference_type i) const noexcept
{ return iterator_[i]; }
/** Subscript of 'element_index', returning mutable Value_type reference. */
- constexpr Value_type& operator[](difference_type i) noexcept
+ constexpr reference operator[](difference_type i) noexcept
{ return iterator_[i]; }
/** Addition-assignment of 'element_count'; Well performing, return *this. */
diff --git a/include/jau/cow_vector.hpp b/include/jau/cow_vector.hpp
index ded50d0..a30cdd4 100644
--- a/include/jau/cow_vector.hpp
+++ b/include/jau/cow_vector.hpp
@@ -120,7 +120,7 @@ namespace jau {
* Using jau::cow_vector::get_snapshot() at construction.
* </p>
*/
- typedef cow_ro_iterator<value_type, storage_t, storage_ref_t, size_type> const_iterator;
+ typedef cow_ro_iterator<storage_t, storage_ref_t> const_iterator;
/**
* Mutable, read-write iterator, holding the write-lock and a store copy until destruction.
@@ -129,7 +129,7 @@ namespace jau {
* and jau::cow_vector::set_store() at destruction.
* </p>
*/
- typedef cow_rw_iterator<value_type, storage_t, storage_ref_t, cow_vector, size_type> iterator;
+ typedef cow_rw_iterator<storage_t, storage_ref_t, cow_vector> iterator;
private:
static constexpr size_type DIFF_MAX = std::numeric_limits<difference_type>::max();