diff options
-rw-r--r-- | include/jau/cow_darray.hpp | 124 | ||||
-rw-r--r-- | include/jau/darray.hpp | 102 |
2 files changed, 225 insertions, 1 deletions
diff --git a/include/jau/cow_darray.hpp b/include/jau/cow_darray.hpp index 8da0399..e1486cd 100644 --- a/include/jau/cow_darray.hpp +++ b/include/jau/cow_darray.hpp @@ -492,10 +492,14 @@ namespace jau { } /** - * Create a new instance from an initializer list. + * Using the `std::initializer_list` requires to *copy* the given value_type objects into this cow_darray. + * + * To utilize more efficient move semantics, see push_back_list() and jau::make_cow_darray(). * * @param initlist initializer_list. * @param alloc allocator + * @see push_back_list() + * @see jau::make_cow_darray() */ constexpr cow_darray(std::initializer_list<value_type> initlist, const allocator_type& alloc = allocator_type()) : store_ref(std::make_shared<storage_t>(initlist, alloc)), sync_atomic(false) @@ -912,6 +916,73 @@ namespace jau { } /** + * Like push_back(), but for more multiple const r-value to copy. + * <p> + * This write operation uses a mutex lock and is blocking this instances' write operations only. + * </p> + * + * @tparam Args + * @param args r-value references to copy into this storage + */ + template <typename... Args> + constexpr_atomic void push_back_list(const Args&... args) + { + std::lock_guard<std::recursive_mutex> lock(mtx_write); + const size_type new_size_ = store_ref->size() + sizeof...(Args); + + if( new_size_ > store_ref->capacity() ) { + // grow and swap all refs + storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, new_size_, + store_ref->growth_factor(), + store_ref->get_allocator_ref() ); + // C++17 fold expression on above C++11 template pack args + ( new_store_ref->push_back( args ), ... ); // @suppress("Syntax error") + { + sc_atomic_critical sync(sync_atomic); + store_ref = std::move(new_store_ref); + } + } else { + // just append .. + // C++17 fold expression on above C++11 template pack args + ( store_ref->push_back( args ), ... ); // @suppress("Syntax error") + } + } + + /** + * Like push_back(), but for more multiple r-value references to move. + * <p> + * This write operation uses a mutex lock and is blocking this instances' write operations only. + * </p> + * + * @tparam Args + * @param args r-value references to move into this storage + * @see jau::make_cow_darray() + */ + template <typename... Args> + constexpr_atomic void push_back_list(Args&&... args) + { + std::lock_guard<std::recursive_mutex> lock(mtx_write); + const size_type new_size_ = store_ref->size() + sizeof...(Args); + + if( new_size_ > store_ref->capacity() ) { + // grow and swap all refs + storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, new_size_, + store_ref->growth_factor(), + store_ref->get_allocator_ref() ); + // C++17 fold expression on above C++11 template pack args + ( new_store_ref->push_back( std::move(args) ), ... ); // @suppress("Syntax error") + { + sc_atomic_critical sync(sync_atomic); + store_ref = std::move(new_store_ref); + } + } else { + // just append .. + // C++17 fold expression on above C++11 template pack args + ( store_ref->push_back( std::move(args) ), ... ); // @suppress("Syntax error") + } + } + + /** * Generic value_type equal comparator to be user defined for e.g. jau::cow_darray::push_back_unique(). * @param a one element of the equality test. * @param b the other element of the equality test. @@ -1021,6 +1092,57 @@ namespace jau { } }; + /** + * Construct a cow_darray<T> instance, initialized by move semantics from the variadic (template pack) argument list. + * + * std::initializer_list<T> enforces to copy the created instances into the container, + * since its iterator references to `const` value_type. + * + * This alternative template passes the r-value argument references to cow_darray::push_back_list(), + * hence using `std::move` without copying semantics. + * + * All argument types must be of same type, i.e. std::is_same. + * The deduced darray<T> instance also uses same type as its Value_type. + * + * @tparam First the first argument type, must be same + * @tparam Next all other argument types, must be same + * @tparam + * @param arg1 the first r-value + * @param argsN the other r-values + * @return the new `cow_darray` + * @see cow_darray::push_back_list() + * @see make_cow_darray() + */ + template <typename First, typename... Next, + // std::enable_if_t< ( std::is_same<First, Next>::value && ... ), bool> = true> + std::enable_if_t< std::conjunction_v<std::is_same<First, Next>... >, bool> = true> + constexpr cow_darray< First > make_cow_darray(First&& arg1, Next&&... argsN) + { + cow_darray< First > d(1 + sizeof...(Next)); + // C++17 fold expression on above C++11 template pack arg1 and argsN + // d.push_back_list( std::forward<First>(arg1), ( std::forward<Next>(argsN), ... ) ); // @suppress("Syntax error") + d.push_back_list( arg1, argsN... ); // @suppress("Syntax error") + return d; + } + + /** + * Complement constructor for cow_darray<T> instance, move semantics initializer for one argument. + * @tparam First + * @tparam Next + * @param arg1 + * @return + * @see cow_darray::push_back() + * @see cow_darray::push_back_list() + * @see make_cow_darray() + */ + template <typename First, typename... Next> + constexpr cow_darray< First > make_cow_darray(First&& arg1) + { + cow_darray< First > d(1); + d.push_back( std::forward<First>(arg1) ); + return d; + } + /**************************************************************************************** ****************************************************************************************/ diff --git a/include/jau/darray.hpp b/include/jau/darray.hpp index 84a209f..53edba7 100644 --- a/include/jau/darray.hpp +++ b/include/jau/darray.hpp @@ -621,8 +621,14 @@ namespace jau { /** * Create a new instance from an initializer list. * + * Using the `std::initializer_list` requires to *copy* the given value_type objects into this darray. + * + * To utilize more efficient move semantics, see push_back_list() and jau::make_darray(). + * * @param initlist initializer_list. * @param alloc allocator + * @see push_back_list() + * @see jau::make_darray() */ constexpr darray(std::initializer_list<value_type> initlist, const allocator_type& alloc = allocator_type()) : alloc_inst( alloc ), begin_( clone_range_foreign(initlist.size(), initlist.begin(), initlist.end()) ), @@ -1103,6 +1109,51 @@ namespace jau { } /** + * Like push_back(), but for more multiple const r-value to copy. + * + * @tparam Args + * @param args r-value references to copy into this storage + */ + template <typename... Args> + constexpr void push_back_list(const Args&... args) + { + const size_type count = sizeof...(Args); + + JAU_DARRAY_PRINTF("push_back_list.copy.0: %zu elems: this %s\n", count, get_info().c_str()); + + if( end_ + count >= storage_end_ ) { + grow_storage_move(size() + count); + } + // C++17 fold expression on above C++11 template pack args + ( new (const_cast<pointer_mutable>(end_++)) value_type( args ), ... ); // @suppress("Syntax error") + + JAU_DARRAY_PRINTF("push_back_list.copy.X: %zu elems: this %s\n", count, get_info().c_str()); + } + + /** + * Like push_back(), but for more multiple r-value references to move. + * + * @tparam Args + * @param args r-value references to move into this storage + * @see jau::make_darray() + */ + template <typename... Args> + constexpr void push_back_list(Args&&... args) + { + const size_type count = sizeof...(Args); + + JAU_DARRAY_PRINTF("push_back_list.move.0: %zu elems: this %s\n", count, get_info().c_str()); + + if( end_ + count >= storage_end_ ) { + grow_storage_move(size() + count); + } + // C++17 fold expression on above C++11 template pack args + ( new (const_cast<pointer_mutable>(end_++)) value_type( std::move(args) ), ... ); // @suppress("Syntax error") + + JAU_DARRAY_PRINTF("push_back_list.move.X: %zu elems: this %s\n", count, get_info().c_str()); + } + + /** * Generic value_type equal comparator to be user defined for e.g. jau::darray::push_back_unique(). * @param a one element of the equality test. * @param b the other element of the equality test. @@ -1206,6 +1257,57 @@ namespace jau { } }; + /** + * Construct a darray<T> instance, initialized by move semantics from the variadic (template pack) argument list. + * + * std::initializer_list<T> enforces to copy the created instances into the container, + * since its iterator references to `const` value_type. + * + * This alternative template passes the r-value argument references to darray::push_back_list(), + * hence using `std::move` without copying semantics. + * + * All argument types must be of same type, i.e. std::is_same. + * The deduced darray<T> instance also uses same type as its Value_type. + * + * @tparam First the first argument type, must be same + * @tparam Next all other argument types, must be same + * @tparam + * @param arg1 the first r-value + * @param argsN the other r-values + * @return the new `darray` + * @see darray::push_back_list() + * @see make_darray() + */ + template <typename First, typename... Next, + // std::enable_if_t< ( std::is_same<First, Next>::value && ... ), bool> = true> + std::enable_if_t< std::conjunction_v<std::is_same<First, Next>... >, bool> = true> + constexpr darray< First > make_darray(First&& arg1, Next&&... argsN) + { + darray< First > d(1 + sizeof...(Next)); + // C++17 fold expression on above C++11 template pack arg1 and argsN + // d.push_back_list( std::forward<First>(arg1), ( std::forward<Next>(argsN), ... ) ); // @suppress("Syntax error") + d.push_back_list( arg1, argsN... ); // @suppress("Syntax error") + return d; + } + + /** + * Complement constructor for darray<T> instance, move semantics initializer for one argument. + * @tparam First + * @tparam Next + * @param arg1 + * @return + * @see darray::push_back() + * @see darray::push_back_list() + * @see make_darray() + */ + template <typename First, typename... Next> + constexpr darray< First > make_darray(First&& arg1) + { + darray< First > d(1); + d.push_back( std::forward<First>(arg1) ); + return d; + } + /**************************************************************************************** ****************************************************************************************/ |