Direct-BT
2.3.1
Direct-BT - Direct Bluetooth Programming.
|
Go to the documentation of this file.
25 #ifndef JAU_COW_DARRAY_HPP_
26 #define JAU_COW_DARRAY_HPP_
35 #include <condition_variable>
124 template <
typename Value_type,
typename Alloc_type = jau::callocator<Value_type>,
typename Size_type = jau::n
size_t,
125 bool use_memmove = std::is_trivially_copyable_v<Value_type>,
126 bool use_realloc = std::is_base_of_v<jau::callocator<Value_type>, Alloc_type>,
206 static constexpr
size_type DIFF_MAX = std::numeric_limits<difference_type>::max();
210 mutable std::recursive_mutex mtx_write;
219 : store_ref(std::make_shared<
storage_t>()), sync_atomic(false) {
237 : store_ref(std::make_shared<
storage_t>(x)), sync_atomic(false) {
255 std::lock_guard<std::recursive_mutex> lock(mtx_write);
260 store_ref = std::move( std::make_shared<storage_t>( x ) );
266 : store_ref(std::make_shared<storage_t>(std::move(x))), sync_atomic(
false) {
273 : store_ref(std::make_shared<storage_t>(std::move(x),
growth_factor, alloc)), sync_atomic(
false) {
286 std::lock_guard<std::recursive_mutex> lock(mtx_write);
288 DARRAY_PRINTF(
"assignment move_0: x %s\n", x.get_info().c_str());
291 store_ref = std::move( std::make_shared<storage_t>( std::move(x) ) );
306 : sync_atomic(false) {
312 x_store_ref = x.store_ref;
314 store_ref = std::make_shared<storage_t>( *x_store_ref );
326 : sync_atomic(false) {
332 x_store_ref = x.store_ref;
334 store_ref = std::make_shared<storage_t>( *x_store_ref,
growth_factor, alloc );
350 : sync_atomic(false) {
356 x_store_ref = x.store_ref;
358 store_ref = std::make_shared<storage_t>( *x_store_ref, _capacity,
growth_factor, alloc );
369 std::lock_guard<std::recursive_mutex> lock(mtx_write);
375 x_store_ref = x.store_ref;
377 storage_ref_t new_store_ref = std::make_shared<storage_t>( *x_store_ref );
380 store_ref = std::move(new_store_ref);
393 std::unique_lock<std::recursive_mutex> lock(x.mtx_write);
397 store_ref = std::move(x.store_ref);
402 x.store_ref =
nullptr;
418 std::unique_lock<std::recursive_mutex> lock1(x.mtx_write, std::defer_lock);
419 std::unique_lock<std::recursive_mutex> lock2( mtx_write, std::defer_lock);
420 std::lock(lock1, lock2);
425 DARRAY_PRINTF(
"assignment move.0: x %s\n", x.get_info().c_str());
426 store_ref = std::move(x.store_ref);
430 x.store_ref =
nullptr;
452 : store_ref(std::make_shared<
storage_t>(_capacity, first.underling(), last.underling(),
growth_factor, alloc)), sync_atomic(false)
471 template<
class InputIt >
474 : store_ref(std::make_shared<
storage_t>(_capacity, first, last,
growth_factor, alloc)), sync_atomic(false)
488 template<
class InputIt >
490 : store_ref(std::make_shared<
storage_t>(first, last, alloc)), sync_atomic(false)
502 : store_ref(std::make_shared<
storage_t>(initlist, alloc)), sync_atomic(false)
551 std::lock_guard<std::recursive_mutex> lock(mtx_write);
553 return std::make_shared<storage_t>( *store_ref );
588 std::lock_guard<std::recursive_mutex> lock(mtx_write);
592 DARRAY_PRINTF(
"set_store: src %s\n", new_store_ref->get_info().c_str());
595 store_ref = std::move( new_store_ref );
667 return store_ref->get_allocator_ref();
672 return store_ref->get_allocator();
681 return store_ref->growth_factor();
694 return store_ref->capacity();
706 return store_ref->empty();
718 return store_ref->size();
734 std::lock_guard<std::recursive_mutex> lock(mtx_write);
735 if( new_capacity > store_ref->capacity() ) {
736 storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, new_capacity,
737 store_ref->growth_factor(),
738 store_ref->get_allocator_ref() );
740 store_ref = std::move(new_store_ref);
752 std::lock_guard<std::recursive_mutex> lock(mtx_write);
756 store_ref = std::move(new_store_ref);
768 std::unique_lock<std::recursive_mutex> lock(mtx_write, std::defer_lock);
769 std::unique_lock<std::recursive_mutex> lock_x(x.mtx_write, std::defer_lock);
770 std::lock(lock, lock_x);
775 x.store_ref = store_ref;
776 store_ref = x_store_ref;
788 std::lock_guard<std::recursive_mutex> lock(mtx_write);
789 if( !store_ref->empty() ) {
790 storage_ref_t new_store_ref = std::make_shared<storage_t>( store_ref->capacity(),
793 store_ref->growth_factor(),
794 store_ref->get_allocator_ref() );
797 store_ref = std::move(new_store_ref);
811 std::lock_guard<std::recursive_mutex> lock(mtx_write);
812 if( store_ref->capacity_reached() ) {
814 storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, store_ref->get_grown_capacity(),
815 store_ref->growth_factor(),
816 store_ref->get_allocator_ref() );
817 new_store_ref->push_back(x);
820 store_ref = std::move(new_store_ref);
824 store_ref->push_back(x);
836 std::lock_guard<std::recursive_mutex> lock(mtx_write);
837 if( store_ref->capacity_reached() ) {
839 storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, store_ref->get_grown_capacity(),
840 store_ref->growth_factor(),
841 store_ref->get_allocator_ref() );
842 new_store_ref->push_back( std::move(x) );
845 store_ref = std::move(new_store_ref);
849 store_ref->push_back( std::move(x) );
863 template<
typename... Args>
866 std::lock_guard<std::recursive_mutex> lock(mtx_write);
867 if( store_ref->capacity_reached() ) {
869 storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, store_ref->get_grown_capacity(),
870 store_ref->growth_factor(),
871 store_ref->get_allocator_ref() );
872 reference res = new_store_ref->emplace_back( std::forward<Args>(args)... );
875 store_ref = std::move(new_store_ref);
880 return store_ref->emplace_back( std::forward<Args>(args)... );
893 template<
class InputIt >
896 std::lock_guard<std::recursive_mutex> lock(mtx_write);
899 if( new_size_ > store_ref->capacity() ) {
901 storage_ref_t new_store_ref = std::make_shared<storage_t>( *store_ref, new_size_,
902 store_ref->growth_factor(),
903 store_ref->get_allocator_ref() );
904 store_ref->push_back( first, last );
907 store_ref = std::move(new_store_ref);
911 store_ref->push_back( first, last );
949 std::lock_guard<std::recursive_mutex> lock(mtx_write);
950 for(
auto it = store_ref->begin(); it != store_ref->end(); ) {
951 if( comparator( *it, x ) ) {
991 if( comparator( *it, x ) ) {
994 if( !all_matching ) {
1011 if( 1 < ++i ) { res.append(
", "); }
1020 ", "+store_ref->get_info()+
1028 template<
typename Value_type,
typename Alloc_type>
1037 template<
typename Value_type,
typename Alloc_type>
1039 if( &rhs == &lhs ) {
1043 rhs_cend += rhs.
size();
1046 template<
typename Value_type,
typename Alloc_type>
1051 template<
typename Value_type,
typename Alloc_type>
1054 rhs_cend += rhs.
size();
1056 lhs_cend += lhs.
size();
1057 return std::lexicographical_compare(rhs.
cbegin(), rhs_cend, lhs.
begin(), lhs_cend);
1060 template<
typename Value_type,
typename Alloc_type>
1062 {
return lhs < rhs; }
1064 template<
typename Value_type,
typename Alloc_type>
1066 {
return !(lhs < rhs); }
1068 template<
typename Value_type,
typename Alloc_type>
1070 {
return !(rhs < lhs); }
1072 template<
typename Value_type,
typename Alloc_type>
#define constexpr_cxx20
constexpr qualifier replacement for C++20 constexpr.
constexpr static const bool uses_memmove
constexpr_atomic cow_darray & operator=(const cow_darray &x)
Like std::vector::operator=(&), assignment.
constexpr_atomic storage_ref_t copy_store()
Returns a new shared_ptr copy of the underlying store, i.e.
std::shared_ptr< storage_t > storage_ref_t
constexpr static const float DEFAULT_GROWTH_FACTOR
Default growth factor using the golden ratio 1.618.
constexpr iterator begin()
Returns an jau::cow_rw_iterator to the first element of this CoW storage.
Implementation of a Copy-On-Write (CoW) read-onlu iterator over immutable value_type storage.
bool darray_tag
Used to determine whether this type is a darray or has a darray, see ::is_darray_type<T>
constexpr const_iterator cbegin() const noexcept
Returns an jau::cow_ro_iterator to the first element of this CoW storage.
constexpr_atomic int erase_matching(const value_type &x, const bool all_matching, equal_comparator comparator)
Erase either the first matching element or all matching elements.
const value_type & const_reference
void print_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::nsize_t skip_frames=2) noexcept
Prints the de-mangled backtrace string separated by newline excluding this function to stderr,...
std::ostream & operator<<(std::ostream &out, const cow_darray< Value_type, Alloc_type > &c)
void write_back() noexcept
Replace the parent's current store with this iterators' instance, unlock the CoW parents' write lock ...
constexpr_atomic void push_back(value_type &&x)
Like std::vector::push_back(), move.
#define constexpr_atomic
Used when designed to declare a function constexpr, but prohibited by its specific implementation.
cow_darray< value_type, allocator_type, size_type, use_memmove, use_realloc, sec_mem > cow_container_t
constexpr_atomic void pop_back() noexcept
Like std::vector::pop_back().
constexpr_atomic cow_darray(const cow_darray &x, const float growth_factor, const allocator_type &alloc)
Creates a new instance, copying all elements from the given array.
constexpr_atomic storage_ref_t snapshot() const noexcept
Returns the current snapshot of the underlying shared storage by reference.
constexpr_atomic size_type size() const noexcept
Like std::vector::size().
darray< value_type, allocator_type, size_type, use_memmove, use_realloc, sec_mem > storage_t
constexpr_cxx20 std::string toString() const noexcept
constexpr_atomic void swap(cow_darray &x) noexcept
Like std::vector::swap().
constexpr_atomic void push_back(InputIt first, InputIt last)
Like std::vector::push_back(), but appends the whole value_type range [first, last).
PRAGMA_DISABLE_WARNING_POP constexpr_cxx20 std::string to_string(const endian &v) noexcept
Return std::string representation of the given jau::endian.
cow_darray & operator=(storage_t &&x)
Like std::vector::operator=(&&), move, but taking the underling jau::darray.
constexpr cow_darray(std::initializer_list< value_type > initlist, const allocator_type &alloc=allocator_type())
Create a new instance from an initializer list.
constexpr_atomic float growth_factor() const noexcept
Returns the growth factor.
constexpr_atomic cow_darray(const cow_darray &x)
Creates a new instance, copying all elements from the given array.
constexpr cow_darray(const storage_t &x)
Implementation of a dynamic linear array storage, aka vector.
cow_rw_iterator< storage_t, storage_ref_t, cow_container_t > iterator
Mutable, read-write iterator, holding the write-lock and a store copy until destruction.
constexpr cow_darray(const storage_t &x, const float growth_factor, const allocator_type &alloc)
constexpr size_type max_size() const noexcept
Returns std::numeric_limits<difference_type>::max() as the maximum array size.
constexpr std::recursive_mutex & get_write_mutex() noexcept
Returns this instances' recursive write mutex, allowing user to implement more complex mutable write ...
void swap(cow_darray< Value_type, Alloc_type > &rhs, cow_darray< Value_type, Alloc_type > &lhs) noexcept
Alloc_type allocator_type
constexpr_atomic cow_darray(cow_darray &&x) noexcept
constexpr_atomic size_type capacity() const noexcept
Like std::vector::empty().
This class provides a RAII-style Sequentially Consistent (SC) data race free (DRF) critical block.
constexpr_cxx20 std::string get_info() const noexcept
constexpr static const bool uses_realloc
constexpr_atomic bool empty() const noexcept
Like std::vector::empty().
constexpr cow_darray(size_type capacity, const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creating an empty instance with initial capacity and other (default) properties.
constexpr cow_darray(storage_t &&x, const float growth_factor, const allocator_type &alloc) noexcept
constexpr_atomic cow_darray(const cow_darray &x, const size_type _capacity, const float growth_factor, const allocator_type &alloc)
Creates a new instance with custom initial storage capacity, copying all elements from the given arra...
void reserve(size_type new_capacity)
Like std::vector::reserve(), increases this instance's capacity to new_capacity.
constexpr cow_darray() noexcept
Default constructor, giving almost zero capacity and zero memory footprint, but the shared empty jau:...
Implementation of a Copy-On-Write (CoW) using jau::darray as the underlying storage,...
constexpr UnaryFunction for_each_const(T &data, UnaryFunction f, std::enable_if_t< is_cow_type< T >::value, bool >=true) noexcept
bool operator<=(const cow_darray< Value_type, Alloc_type > &rhs, const cow_darray< Value_type, Alloc_type > &lhs)
const allocator_type & get_allocator_ref() const noexcept
constexpr_atomic cow_darray & operator=(cow_darray &&x) noexcept
Like std::vector::operator=(&&), move.
constexpr_atomic reference emplace_back(Args &&... args)
Like std::vector::emplace_back(), construct a new element in place at the end().
std::make_signed< size_type >::type difference_type
constexpr bool is_end() const noexcept
Returns true, if this iterator points to end().
allocator_type get_allocator() const noexcept
bool operator>(const cow_darray< Value_type, Alloc_type > &rhs, const cow_darray< Value_type, Alloc_type > &lhs)
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
bool(* equal_comparator)(const value_type &a, const value_type &b)
Generic value_type equal comparator to be user defined for e.g.
cow_darray & operator=(const storage_t &x)
Like std::vector::operator=(&), assignment, but copying from the underling jau::darray.
constexpr_atomic void clear() noexcept
Like std::vector::clear(), but ending with zero capacity.
constexpr_cxx20 std::string get_info() const noexcept
const value_type * const_pointer
A simple allocator using POSIX C functions: ::malloc(), ::free() and ::realloc().
constexpr cow_darray(storage_t &&x) noexcept
bool operator!=(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
Implementation of a Copy-On-Write (CoW) read-write iterator over mutable value_type storage.
constexpr_atomic void push_back(const value_type &x)
Like std::vector::push_back(), copy.
cow_ro_iterator< storage_t, storage_ref_t, cow_container_t > const_iterator
Immutable, read-only const_iterator, lock-free, holding the current shared store reference until dest...
constexpr_atomic void set_store(storage_ref_t &&new_store_ref) noexcept
Replace the current store with the given instance, potentially acquired via jau::cow_darray::copy_sto...
bool operator>=(const cow_darray< Value_type, Alloc_type > &rhs, const cow_darray< Value_type, Alloc_type > &lhs)
constexpr void erase()
Erases the element at the current position.
constexpr cow_darray(const size_type _capacity, InputIt first, InputIt last, const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creates a new instance with custom initial storage capacity, copying all elements from the given temp...
bool operator==(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
constexpr cow_darray(const size_type _capacity, const_iterator first, const_iterator last, const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creates a new instance with custom initial storage capacity, copying all elements from the given cons...
#define DARRAY_PRINTF(...)
bool operator<(const cow_darray< Value_type, Alloc_type > &rhs, const cow_darray< Value_type, Alloc_type > &lhs)
constexpr_atomic bool push_back_unique(const value_type &x, equal_comparator comparator)
Like std::vector::push_back(), but only if the newly added element does not yet exist.
constexpr cow_darray(InputIt first, InputIt last, const allocator_type &alloc=allocator_type())
Creates a new instance, copying all elements from the given template input-iterator value_type range ...
constexpr static const bool uses_secmem