diff options
author | Sven Gothel <[email protected]> | 2021-01-07 09:08:03 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2021-01-07 09:08:03 +0100 |
commit | a2a21c4be8673f2c6ec603f37ce53fb5237f727d (patch) | |
tree | 8d1e68c7d7bdb92a1703ddab64571ab4b7249c12 /include/jau/cow_darray.hpp | |
parent | 95c6d559f66ea462046d4c1663b228461822341d (diff) |
cow_darray: Fail safe API: Only [c]begin() iterator retrieval, leave other operations on the cow_[ro|rw]_iterator avoding data races
These changes have been adopted to cow_vector as well, still deprecated now.
To allow data-race free operations using iterators from a potentially mutated CoW,
only one cow_darray::begin() const_iterator or iterator should be retrieved from this CoW
and all further operations shall use its
jau::cow_ro_iterator::size(), jau::cow_ro_iterator::begin() and jau::cow_ro_iterator::end()
- or its respective variant from jau::cow_rw_iterator.
Removed from cow_darray:
- 'const_iterator begin() const' // ambiguous mutable/immutable overload
- 'const_iterator cend()' // fetch from cow_ro_iterator::end()
- 'iterator end()' // fetch from cow_rw_iterator::end()
cow_[ro|rw]_iterator:
- private constructor w/ fried to cow_darray, .. only allow copy-ctor etc, not allowing to set false pointer
- Added size(), begin() and end(): Allowing data-race free operations
- full typedefs
- Holds the 'begin iterator' internally to implement begin() and end()
+++
Added new convenience template Type Traits and functions:
- 'template< class T > is_cow_type<T>::value' compile-time Type Trait,
determining whether the given template class is a CoW type, e.g. jau::cow_darray,
jau::cow_vector or any of their iterator.
For both, cow_type or any other using above 'is_cow_type<T>' trait:
- find_const(T& data)
- for_each_const(T& data)
- for_each_fidelity(T& data)
++++
Performance: No regression, even a little more speed-up.
Diffstat (limited to 'include/jau/cow_darray.hpp')
-rw-r--r-- | include/jau/cow_darray.hpp | 101 |
1 files changed, 42 insertions, 59 deletions
diff --git a/include/jau/cow_darray.hpp b/include/jau/cow_darray.hpp index e9926af..44582da 100644 --- a/include/jau/cow_darray.hpp +++ b/include/jau/cow_darray.hpp @@ -93,16 +93,29 @@ namespace jau { * jau::cow_darray::get_write_mutex(), jau::cow_darray::copy_store() and jau::cow_darray::set_store().<br> * See example in jau::cow_darray::set_store() * </p> - * + * <p> + * To allow data-race free operations using iterators from a potentially mutated CoW, + * only one cow_darray::begin() const_iterator or iterator should be retrieved from this CoW + * and all further operations shall use its + * jau::cow_ro_iterator::size(), jau::cow_ro_iterator::begin() and jau::cow_ro_iterator::end() + * - or its respective variant from jau::cow_rw_iterator. * </p> * See also: * <pre> * - Sequentially Consistent (SC) ordering or SC-DRF (data race free) <https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering> * - std::memory_order <https://en.cppreference.com/w/cpp/atomic/memory_order> * </pre> + * @see jau::cow_darray::cbegin() * @see jau::cow_ro_iterator + * @see jau::cow_ro_iterator::size() + * @see jau::cow_ro_iterator::begin() + * @see jau::cow_ro_iterator::end() * @see jau::for_each_fidelity + * @see jau::cow_darray::begin() * @see jau::cow_rw_iterator + * @see jau::cow_rw_iterator::size() + * @see jau::cow_rw_iterator::begin() + * @see jau::cow_rw_iterator::end() */ template <typename Value_type, typename Alloc_type = callocator<Value_type>, typename Size_type = jau::nsize_t> class cow_darray @@ -125,6 +138,8 @@ namespace jau { typedef darray<value_type, allocator_type, size_type> storage_t; typedef std::shared_ptr<storage_t> storage_ref_t; + typedef cow_darray<value_type, allocator_type, size_type> cow_container_t; + /** * Immutable, read-only const_iterator, lock-free, * holding the current shared store reference until destruction. @@ -138,10 +153,13 @@ namespace jau { * Also see jau::for_each_fidelity to iterate through in this good faith fashion. * </p> * @see jau::cow_ro_iterator + * @see jau::cow_ro_iterator::size() + * @see jau::cow_ro_iterator::begin() + * @see jau::cow_ro_iterator::end() * @see jau::for_each_fidelity * @see jau::cow_rw_iterator */ - typedef cow_ro_iterator<storage_t, storage_ref_t, cow_darray> const_iterator; + typedef cow_ro_iterator<storage_t, storage_ref_t, cow_container_t> const_iterator; /** * Mutable, read-write iterator, holding the write-lock and a store copy until destruction. @@ -154,11 +172,13 @@ namespace jau { * consider using jau::cow_rw_iterator if elements won't get mutated * or any changes can be discarded. * </p> - * @see jau::cow_ro_iterator - * @see jau::for_each_fidelity * @see jau::cow_rw_iterator + * @see jau::cow_rw_iterator::size() + * @see jau::cow_rw_iterator::begin() + * @see jau::cow_rw_iterator::end() + * @see jau::cow_ro_iterator */ - typedef cow_rw_iterator<storage_t, storage_ref_t, cow_darray> iterator; + typedef cow_rw_iterator<storage_t, storage_ref_t, cow_container_t> iterator; // typedef std::reverse_iterator<iterator> reverse_iterator; // typedef std::reverse_iterator<const_iterator> const_reverse_iterator; @@ -410,86 +430,49 @@ namespace jau { // const_iterator, non mutable, read-only - /** - * Returns a jau::cow_darray::const_iterator of type jau::cow_ro_iterator. - * <p> - * This method variant is only chosen if the container is const. - * </p> - * @return jau::cow_darray::const_iterator of type jau::cow_ro_iterator - * @see jau::cow_ro_iterator - * @see jau::for_each_fidelity - */ - constexpr const_iterator begin() const noexcept { - return const_iterator(get_snapshot(), store_ref->cbegin()); - } + // Removed for clarity: "constexpr const_iterator begin() const noexcept" /** - * Returns a jau::cow_darray::const_iterator of type jau::cow_ro_iterator. + * Returns an jau::cow_ro_iterator to the first element of this CoW storage. * <p> * This method is the preferred choice if the use case allows, * read remarks in jau::cow_ro_iterator. * </p> - * @return jau::cow_darray::const_iterator of type jau::cow_ro_iterator - * @see jau::cow_ro_iterator - * @see jau::for_each_fidelity - */ - constexpr const_iterator cbegin() const noexcept { - return const_iterator(get_snapshot(), store_ref->cbegin()); - } - - /** - * Returns a jau::cow_darray::const_iterator of type jau::cow_ro_iterator. - * <p> - * This method variant is only chosen if the container is const. - * </p> - * @return jau::cow_darray::const_iterator of type jau::cow_ro_iterator - * @see jau::cow_ro_iterator - * @see jau::for_each_fidelity - */ - constexpr const_iterator end() const noexcept { - return const_iterator(get_snapshot(), store_ref->cend()); - } - - /** - * Returns a jau::cow_darray::const_iterator of type jau::cow_ro_iterator. * <p> - * This method is the preferred choice if the use case allows, - * read remarks in jau::cow_ro_iterator. + * Use jau::cow_ro_iterator::end() on this returned const_iterator + * to retrieve the end const_iterator in a data-race free fashion. * </p> * @return jau::cow_darray::const_iterator of type jau::cow_ro_iterator * @see jau::cow_ro_iterator + * @see jau::cow_ro_iterator::size() + * @see jau::cow_ro_iterator::begin() + * @see jau::cow_ro_iterator::end() * @see jau::for_each_fidelity */ - constexpr const_iterator cend() const noexcept { - return const_iterator(get_snapshot(), store_ref->cend()); + constexpr const_iterator cbegin() const noexcept { + return const_iterator(get_snapshot(), store_ref->cbegin()); } // iterator, mutable, read-write /** - * Returns a jau::cow_darray::iterator of type jau::cow_rw_iterator. + * Returns an jau::cow_rw_iterator to the first element of this CoW storage. * <p> * Acquiring this mutable iterator has considerable costs attached, * read remarks in jau::cow_rw_iterator. * </p> - * @return jau::cow_darray::iterator of type jau::cow_rw_iterator - * @see jau::cow_rw_iterator - */ - constexpr iterator begin() noexcept { - return iterator(*this, [](storage_ref_t& new_store) -> typename storage_t::iterator { return new_store->begin(); } ); - } - - /** - * Returns a jau::cow_darray::iterator of type jau::cow_rw_iterator. * <p> - * Acquiring this mutable iterator has considerable costs attached, - * read remarks in jau::cow_rw_iterator. + * Use jau::cow_rw_iterator::end() on this returned iterator + * to retrieve the end iterator in a data-race free fashion. * </p> * @return jau::cow_darray::iterator of type jau::cow_rw_iterator * @see jau::cow_rw_iterator + * @see jau::cow_rw_iterator::size() + * @see jau::cow_rw_iterator::begin() + * @see jau::cow_rw_iterator::end() */ - constexpr iterator end() noexcept { - return iterator(*this, [](storage_ref_t& new_store) -> typename storage_t::iterator { return new_store->end(); } ); + constexpr iterator begin() noexcept { + return iterator(*this, [](storage_ref_t& new_store) -> typename storage_t::iterator { return new_store->begin(); } ); } // read access |