diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index b2c0753a..6d875d1d 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -147,7 +147,7 @@ struct deque_iterator decltype(curr_ptr) beginptr; if (pos < 0) { - size_type diff{static_cast(this->itercontent.end_ptr - curr_ptr)}; + size_type diff{static_cast(this->itercontent.end_ptr - curr_ptr) - 1u}; constexpr size_type zero{}; size_type abspos{static_cast(zero - unsignedpos)}; diff += abspos; @@ -183,7 +183,7 @@ struct deque_iterator } else { - size_type diff{static_cast(this->itercontent.end_ptr - curr_ptr)}; + size_type diff{static_cast(this->itercontent.end_ptr - curr_ptr) - 1u}; diff += unsignedpos; this->itercontent.curr_ptr = (beginptr = *(controllerptr -= diff / blocksize)) + (blocksizem1 - diff % blocksize); } @@ -246,7 +246,7 @@ inline constexpr ::std::ptrdiff_t deque_iter_difference_common(::fast_io::contai { ::std::ptrdiff_t controllerdiff{a.controller_ptr - b.controller_ptr}; constexpr ::std::ptrdiff_t blocksizedf{static_cast<::std::ptrdiff_t>(::fast_io::containers::details::deque_block_size)}; - return controllerdiff * blocksizedf + (a.curr_ptr - b.begin_ptr) + (b.begin_ptr - b.curr_ptr); + return controllerdiff * blocksizedf + (a.curr_ptr - a.begin_ptr) - (b.curr_ptr - b.begin_ptr); } template @@ -282,10 +282,11 @@ inline constexpr void deque_destroy_controller(controllerblocktype *controllerpt } else { - ::std::size_t n{static_cast<::std::size_t>(controller.controller_after_ptr - controller.controller_start_ptr) * sizeof(void *)}; + // `controller_after_ptr` points at the extra sentinel slot (allocated). Include it in sized deallocation. + ::std::size_t n{(static_cast<::std::size_t>(controller.controller_after_ptr - controller.controller_start_ptr) + 1u) * sizeof(void *)}; allocator::deallocate_n(controller.controller_start_ptr, n); } - + controller.controller_start_ptr = nullptr; } @@ -357,13 +358,17 @@ inline constexpr void deque_init_grow_common_controllerallocate_impl(dequecontro template inline constexpr void deque_init_grow_common_noalign_impl(dequecontroltype &controller, ::std::size_t total_block_size, ::std::size_t mid) noexcept { - ::fast_io::containers::details::deque_init_grow_common_controllerallocate_impl(controller, total_block_size, mid, static_cast(allocator::allocate_zero(total_block_size))); + using replacetype = typename dequecontroltype::replacetype; + constexpr ::std::size_t bytes_per_unit{sizeof(replacetype)}; + ::fast_io::containers::details::deque_init_grow_common_controllerallocate_impl(controller, total_block_size, mid, static_cast(allocator::allocate_zero(total_block_size * bytes_per_unit))); } template inline constexpr void deque_init_grow_common_align_impl(dequecontroltype &controller, ::std::size_t align, ::std::size_t total_block_size, ::std::size_t mid) noexcept { - ::fast_io::containers::details::deque_init_grow_common_controllerallocate_impl(controller, total_block_size, mid, static_cast(allocator::allocate_zero_aligned(align, total_block_size))); + using replacetype = typename dequecontroltype::replacetype; + constexpr ::std::size_t bytes_per_unit{sizeof(replacetype)}; + ::fast_io::containers::details::deque_init_grow_common_controllerallocate_impl(controller, total_block_size, mid, static_cast(allocator::allocate_aligned_zero(align, total_block_size * bytes_per_unit))); } template @@ -397,7 +402,8 @@ inline constexpr void deque_reallocate_controller_block_common_impl(dequecontrol ::std::size_t front_block_index{static_cast<::std::size_t>(controller.front_block.controller_ptr - controller.controller_block.controller_start_ptr)}; ::std::size_t back_block_index{static_cast<::std::size_t>(controller.back_block.controller_ptr - controller.controller_block.controller_start_ptr)}; - auto block_temp{allocator::reallocate_n(controller.controller_block.controller_start_ptr, old_size * sizeof(void *), (new_size + 1u) * sizeof(void *))}; + // `controller_after_ptr` points at the extra sentinel slot (allocated). Include it in sized reallocation. + auto block_temp{allocator::reallocate_n(controller.controller_block.controller_start_ptr, (old_size + 1u) * sizeof(void *), (new_size + 1u) * sizeof(void *))}; controller.controller_block.controller_start_ptr = static_cast(block_temp); @@ -419,14 +425,14 @@ inline constexpr T **make_blocks_balance(T **begin, T **end, T **b, T **e) noexc if (begin == b) { T *t = end[-1]; - ::std::copy(b, e, begin + 1); + ::fast_io::freestanding::overlapped_copy(b, e, begin + 1); *begin = t; return begin + 1u; } else { T *t = *begin; - ::std::copy(b, e, begin); + ::fast_io::freestanding::overlapped_copy(b, e, begin); end[-1] = t; return begin; } @@ -525,13 +531,14 @@ inline constexpr void deque_grow_front_common_impl(dequecontroltype &controller) void *block_temp{}; + constexpr ::std::size_t bytes_to_allocate{block_size * sizeof(typename dequecontroltype::replacetype)}; if constexpr (align <= allocator::default_alignment) { - block_temp = allocator::allocate(block_size); + block_temp = allocator::allocate(bytes_to_allocate); } else { - block_temp = allocator::allocate_zero_aligned(align, block_size); + block_temp = allocator::allocate_aligned_zero(align, bytes_to_allocate); } *--controller.controller_block.controller_start_reserved_ptr = reinterpret_cast(block_temp); @@ -578,13 +585,14 @@ inline constexpr void deque_grow_back_common_impl(dequecontroltype &controller) void *block_temp{}; + constexpr ::std::size_t bytes_to_allocate{block_size * sizeof(typename dequecontroltype::replacetype)}; if constexpr (align <= allocator::default_alignment) { - block_temp = allocator::allocate(block_size); + block_temp = allocator::allocate(bytes_to_allocate); } else { - block_temp = allocator::allocate_zero_aligned(align, block_size); + block_temp = allocator::allocate_aligned_zero(align, bytes_to_allocate); } *controller.controller_block.controller_after_reserved_ptr = reinterpret_cast(block_temp); @@ -751,11 +759,22 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE grow_back(); } auto currptr{controller.back_block.curr_ptr}; - if constexpr (!::std::is_trivially_constructible_v) + ::std::construct_at(currptr, ::std::forward(args)...); + if (++controller.back_block.curr_ptr == controller.back_block.end_ptr) [[unlikely]] { - ::std::construct_at(currptr, ::std::forward(args)...); + if (controller.back_block.curr_ptr != controller.back_block.end_ptr) + { + return; + } + auto ctrl{controller.back_block.controller_ptr}; + if (ctrl && ctrl[1] != nullptr) + { + return; + } + // Allocate/attach a block after `back_block`, then restore `back_block` to the full block. + grow_back(); + back_backspace(); } - ++controller.back_block.curr_ptr; return *currptr; } @@ -829,10 +848,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { grow_front(); } - if constexpr (!::std::is_trivially_constructible_v) - { - ::std::construct_at(--controller.front_block.curr_ptr, ::std::forward(args)...); - } + ::std::construct_at(--controller.front_block.curr_ptr, ::std::forward(args)...); return *controller.front_block.curr_ptr; }