/src/immer/immer/detail/arrays/with_capacity.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // immer: immutable data structures for C++ |
3 | | // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente |
4 | | // |
5 | | // This software is distributed under the Boost Software License, Version 1.0. |
6 | | // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt |
7 | | // |
8 | | |
9 | | #pragma once |
10 | | |
11 | | #include <immer/config.hpp> |
12 | | #include <immer/detail/arrays/no_capacity.hpp> |
13 | | |
14 | | #include <cassert> |
15 | | #include <cstddef> |
16 | | #include <stdexcept> |
17 | | |
18 | | namespace immer { |
19 | | namespace detail { |
20 | | namespace arrays { |
21 | | |
22 | | template <typename T, typename MemoryPolicy> |
23 | | struct with_capacity |
24 | | { |
25 | | using no_capacity_t = no_capacity<T, MemoryPolicy>; |
26 | | |
27 | | using node_t = node<T, MemoryPolicy>; |
28 | | using edit_t = typename MemoryPolicy::transience_t::edit; |
29 | | using size_t = std::size_t; |
30 | | |
31 | | node_t* ptr; |
32 | | size_t size; |
33 | | size_t capacity; |
34 | | |
35 | | static const with_capacity& empty() |
36 | 183k | { |
37 | 183k | static const with_capacity empty_{node_t::make_n(1), 0, 1}; |
38 | 183k | return empty_; |
39 | 183k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::empty() Line | Count | Source | 36 | 22.1k | { | 37 | 22.1k | static const with_capacity empty_{node_t::make_n(1), 0, 1}; | 38 | 22.1k | return empty_; | 39 | 22.1k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::empty() Line | Count | Source | 36 | 161k | { | 37 | 161k | static const with_capacity empty_{node_t::make_n(1), 0, 1}; | 38 | 161k | return empty_; | 39 | 161k | } |
|
40 | | |
41 | | with_capacity(node_t* p, size_t s, size_t c) |
42 | | : ptr{p} |
43 | | , size{s} |
44 | | , capacity{c} |
45 | 377k | { |
46 | 377k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::with_capacity(immer::detail::arrays::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >*, unsigned long, unsigned long) Line | Count | Source | 45 | 53.3k | { | 46 | 53.3k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::with_capacity(immer::detail::arrays::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >*, unsigned long, unsigned long) Line | Count | Source | 45 | 324k | { | 46 | 324k | } |
|
47 | | |
48 | | with_capacity(const with_capacity& other) |
49 | | : with_capacity{other.ptr, other.size, other.capacity} |
50 | 183k | { |
51 | 183k | inc(); |
52 | 183k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> > const&) Line | Count | Source | 50 | 22.1k | { | 51 | 22.1k | inc(); | 52 | 22.1k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > const&) Line | Count | Source | 50 | 161k | { | 51 | 161k | inc(); | 52 | 161k | } |
|
53 | | |
54 | | with_capacity(const no_capacity_t& other) |
55 | | : with_capacity{other.ptr, other.size, other.size} |
56 | 18.1k | { |
57 | 18.1k | inc(); |
58 | 18.1k | } |
59 | | |
60 | | with_capacity(with_capacity&& other) |
61 | | : with_capacity{empty()} |
62 | 176k | { |
63 | 176k | swap(*this, other); |
64 | 176k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&&) Line | Count | Source | 62 | 18.1k | { | 63 | 18.1k | swap(*this, other); | 64 | 18.1k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&&) Line | Count | Source | 62 | 158k | { | 63 | 158k | swap(*this, other); | 64 | 158k | } |
|
65 | | |
66 | | with_capacity& operator=(const with_capacity& other) |
67 | | { |
68 | | auto next = other; |
69 | | swap(*this, next); |
70 | | return *this; |
71 | | } |
72 | | |
73 | | with_capacity& operator=(with_capacity&& other) |
74 | 404k | { |
75 | 404k | swap(*this, other); |
76 | 404k | return *this; |
77 | 404k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::operator=(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&&) Line | Count | Source | 74 | 31.2k | { | 75 | 31.2k | swap(*this, other); | 76 | 31.2k | return *this; | 77 | 31.2k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::operator=(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&&) Line | Count | Source | 74 | 373k | { | 75 | 373k | swap(*this, other); | 76 | 373k | return *this; | 77 | 373k | } |
|
78 | | |
79 | | friend void swap(with_capacity& x, with_capacity& y) |
80 | 581k | { |
81 | 581k | using std::swap; |
82 | 581k | swap(x.ptr, y.ptr); |
83 | 581k | swap(x.size, y.size); |
84 | 581k | swap(x.capacity, y.capacity); |
85 | 581k | } immer::detail::arrays::swap(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&, immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&) Line | Count | Source | 80 | 49.4k | { | 81 | 49.4k | using std::swap; | 82 | 49.4k | swap(x.ptr, y.ptr); | 83 | 49.4k | swap(x.size, y.size); | 84 | 49.4k | swap(x.capacity, y.capacity); | 85 | 49.4k | } |
immer::detail::arrays::swap(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&, immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&) Line | Count | Source | 80 | 532k | { | 81 | 532k | using std::swap; | 82 | 532k | swap(x.ptr, y.ptr); | 83 | 532k | swap(x.size, y.size); | 84 | 532k | swap(x.capacity, y.capacity); | 85 | 532k | } |
|
86 | | |
87 | 377k | ~with_capacity() { dec(); } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::~with_capacity() Line | Count | Source | 87 | 53.3k | ~with_capacity() { dec(); } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::~with_capacity() Line | Count | Source | 87 | 324k | ~with_capacity() { dec(); } |
|
88 | | |
89 | | void inc() |
90 | 201k | { |
91 | 201k | using immer::detail::get; |
92 | 201k | ptr->refs().inc(); |
93 | 201k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::inc() Line | Count | Source | 90 | 40.2k | { | 91 | 40.2k | using immer::detail::get; | 92 | 40.2k | ptr->refs().inc(); | 93 | 40.2k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::inc() Line | Count | Source | 90 | 161k | { | 91 | 161k | using immer::detail::get; | 92 | 161k | ptr->refs().inc(); | 93 | 161k | } |
|
94 | | |
95 | | void dec() |
96 | 377k | { |
97 | 377k | using immer::detail::get; |
98 | 377k | if (ptr->refs().dec()) |
99 | 163k | node_t::delete_n(ptr, size, capacity); |
100 | 377k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::dec() Line | Count | Source | 96 | 53.3k | { | 97 | 53.3k | using immer::detail::get; | 98 | 53.3k | if (ptr->refs().dec()) | 99 | 0 | node_t::delete_n(ptr, size, capacity); | 100 | 53.3k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::dec() Line | Count | Source | 96 | 324k | { | 97 | 324k | using immer::detail::get; | 98 | 324k | if (ptr->refs().dec()) | 99 | 163k | node_t::delete_n(ptr, size, capacity); | 100 | 324k | } |
|
101 | | |
102 | | const T* data() const { return ptr->data(); } |
103 | 1.67M | T* data() { return ptr->data(); } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::data() Line | Count | Source | 103 | 1.47M | T* data() { return ptr->data(); } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::data() Line | Count | Source | 103 | 205k | T* data() { return ptr->data(); } |
|
104 | | |
105 | | T* data_mut(edit_t e) |
106 | | { |
107 | | if (!ptr->can_mutate(e)) { |
108 | | auto p = node_t::copy_e(e, capacity, ptr, size); |
109 | | dec(); |
110 | | ptr = p; |
111 | | } |
112 | | return data(); |
113 | | } |
114 | | |
115 | | operator no_capacity_t() const |
116 | 2.74k | { |
117 | 2.74k | if (size == capacity) { |
118 | 1.05k | ptr->refs().inc(); |
119 | 1.05k | return {ptr, size}; |
120 | 1.69k | } else { |
121 | 1.69k | return {node_t::copy_n(size, ptr, size), size}; |
122 | 1.69k | } |
123 | 2.74k | } |
124 | | |
125 | | template <typename Iter, |
126 | | typename Sent, |
127 | | std::enable_if_t<is_forward_iterator_v<Iter> && |
128 | | compatible_sentinel_v<Iter, Sent>, |
129 | | bool> = true> |
130 | | static with_capacity from_range(Iter first, Sent last) |
131 | | { |
132 | | auto count = static_cast<size_t>(detail::distance(first, last)); |
133 | | if (count == 0) |
134 | | return empty(); |
135 | | else |
136 | | return {node_t::copy_n(count, first, last), count, count}; |
137 | | } |
138 | | |
139 | | template <typename U> |
140 | | static with_capacity from_initializer_list(std::initializer_list<U> values) |
141 | | { |
142 | | using namespace std; |
143 | | return from_range(begin(values), end(values)); |
144 | | } |
145 | | |
146 | | static with_capacity from_fill(size_t n, T v) |
147 | | { |
148 | | return {node_t::fill_n(n, v), n, n}; |
149 | | } |
150 | | |
151 | | template <typename Fn> |
152 | | void for_each_chunk(Fn&& fn) const |
153 | | { |
154 | | std::forward<Fn>(fn)(data(), data() + size); |
155 | | } |
156 | | |
157 | | template <typename Fn> |
158 | | bool for_each_chunk_p(Fn&& fn) const |
159 | | { |
160 | | return std::forward<Fn>(fn)(data(), data() + size); |
161 | | } |
162 | | |
163 | | const T& get(std::size_t index) const { return data()[index]; } |
164 | | |
165 | | const T& get_check(std::size_t index) const |
166 | | { |
167 | | if (index >= size) |
168 | | IMMER_THROW(std::out_of_range{"out of range"}); |
169 | | return data()[index]; |
170 | | } |
171 | | |
172 | | bool equals(const with_capacity& other) const |
173 | | { |
174 | | return ptr == other.ptr || |
175 | | (size == other.size && |
176 | | std::equal(data(), data() + size, other.data())); |
177 | | } |
178 | | |
179 | | static size_t recommend_up(size_t sz, size_t cap) |
180 | 163k | { |
181 | 163k | auto max = std::numeric_limits<size_t>::max(); |
182 | 163k | return sz <= cap ? cap |
183 | 163k | : cap >= max / 2 ? max |
184 | | /* otherwise */ |
185 | 22.0k | : std::max(2 * cap, sz); |
186 | 163k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::recommend_up(unsigned long, unsigned long) Line | Count | Source | 180 | 11.6k | { | 181 | 11.6k | auto max = std::numeric_limits<size_t>::max(); | 182 | 11.6k | return sz <= cap ? cap | 183 | 11.6k | : cap >= max / 2 ? max | 184 | | /* otherwise */ | 185 | 10.4k | : std::max(2 * cap, sz); | 186 | 11.6k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::recommend_up(unsigned long, unsigned long) Line | Count | Source | 180 | 152k | { | 181 | 152k | auto max = std::numeric_limits<size_t>::max(); | 182 | 152k | return sz <= cap ? cap | 183 | 152k | : cap >= max / 2 ? max | 184 | | /* otherwise */ | 185 | 11.5k | : std::max(2 * cap, sz); | 186 | 152k | } |
|
187 | | |
188 | | static size_t recommend_down(size_t sz, size_t cap) |
189 | 6.99k | { |
190 | 6.99k | return sz == 0 ? 1 |
191 | 6.99k | : sz < cap / 2 ? sz * 2 |
192 | 3.92k | : |
193 | 3.92k | /* otherwise */ cap; |
194 | 6.99k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::recommend_down(unsigned long, unsigned long) Line | Count | Source | 189 | 1.22k | { | 190 | 1.22k | return sz == 0 ? 1 | 191 | 1.22k | : sz < cap / 2 ? sz * 2 | 192 | 673 | : | 193 | 673 | /* otherwise */ cap; | 194 | 1.22k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::recommend_down(unsigned long, unsigned long) Line | Count | Source | 189 | 5.76k | { | 190 | 5.76k | return sz == 0 ? 1 | 191 | 5.76k | : sz < cap / 2 ? sz * 2 | 192 | 3.25k | : | 193 | 3.25k | /* otherwise */ cap; | 194 | 5.76k | } |
|
195 | | |
196 | | with_capacity push_back(T value) const |
197 | 147k | { |
198 | 147k | auto cap = recommend_up(size + 1, capacity); |
199 | 147k | auto p = node_t::copy_n(cap, ptr, size); |
200 | 147k | IMMER_TRY { |
201 | 147k | new (p->data() + size) T{std::move(value)}; |
202 | 147k | return {p, size + 1, cap}; |
203 | 147k | } |
204 | 147k | IMMER_CATCH (...) { |
205 | 0 | node_t::delete_n(p, size, cap); |
206 | 0 | IMMER_RETHROW; |
207 | 0 | } |
208 | 147k | } |
209 | | |
210 | | void push_back_mut(edit_t e, T value) |
211 | 1.68M | { |
212 | 1.68M | if (ptr->can_mutate(e) && capacity > size) { |
213 | 1.66M | new (data() + size) T{std::move(value)}; |
214 | 1.66M | ++size; |
215 | 1.66M | } else { |
216 | 16.1k | auto cap = recommend_up(size + 1, capacity); |
217 | 16.1k | auto p = node_t::copy_e(e, cap, ptr, size); |
218 | 16.1k | IMMER_TRY { |
219 | 16.1k | new (p->data() + size) T{std::move(value)}; |
220 | 16.1k | *this = {p, size + 1, cap}; |
221 | 16.1k | } |
222 | 16.1k | IMMER_CATCH (...) { |
223 | 0 | node_t::delete_n(p, size, cap); |
224 | 0 | IMMER_RETHROW; |
225 | 0 | } |
226 | 16.1k | } |
227 | 1.68M | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::push_back_mut(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, int) Line | Count | Source | 211 | 1.48M | { | 212 | 1.48M | if (ptr->can_mutate(e) && capacity > size) { | 213 | 1.47M | new (data() + size) T{std::move(value)}; | 214 | 1.47M | ++size; | 215 | 1.47M | } else { | 216 | 11.6k | auto cap = recommend_up(size + 1, capacity); | 217 | 11.6k | auto p = node_t::copy_e(e, cap, ptr, size); | 218 | 11.6k | IMMER_TRY { | 219 | 11.6k | new (p->data() + size) T{std::move(value)}; | 220 | 11.6k | *this = {p, size + 1, cap}; | 221 | 11.6k | } | 222 | 11.6k | IMMER_CATCH (...) { | 223 | 0 | node_t::delete_n(p, size, cap); | 224 | 0 | IMMER_RETHROW; | 225 | 0 | } | 226 | 11.6k | } | 227 | 1.48M | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::push_back_mut(immer::no_transience_policy::apply<immer::free_list_heap_policy<immer::cpp_heap, 1024ul> >::type::edit, int) Line | Count | Source | 211 | 201k | { | 212 | 201k | if (ptr->can_mutate(e) && capacity > size) { | 213 | 196k | new (data() + size) T{std::move(value)}; | 214 | 196k | ++size; | 215 | 196k | } else { | 216 | 4.57k | auto cap = recommend_up(size + 1, capacity); | 217 | 4.57k | auto p = node_t::copy_e(e, cap, ptr, size); | 218 | 4.57k | IMMER_TRY { | 219 | 4.57k | new (p->data() + size) T{std::move(value)}; | 220 | 4.57k | *this = {p, size + 1, cap}; | 221 | 4.57k | } | 222 | 4.57k | IMMER_CATCH (...) { | 223 | 0 | node_t::delete_n(p, size, cap); | 224 | 0 | IMMER_RETHROW; | 225 | 0 | } | 226 | 4.57k | } | 227 | 201k | } |
|
228 | | |
229 | | with_capacity assoc(std::size_t idx, T value) const |
230 | | { |
231 | | auto p = node_t::copy_n(capacity, ptr, size); |
232 | | IMMER_TRY { |
233 | | p->data()[idx] = std::move(value); |
234 | | return {p, size, capacity}; |
235 | | } |
236 | | IMMER_CATCH (...) { |
237 | | node_t::delete_n(p, size, capacity); |
238 | | IMMER_RETHROW; |
239 | | } |
240 | | } |
241 | | |
242 | | void assoc_mut(edit_t e, std::size_t idx, T value) |
243 | | { |
244 | | if (ptr->can_mutate(e)) { |
245 | | data()[idx] = std::move(value); |
246 | | } else { |
247 | | auto p = node_t::copy_n(capacity, ptr, size); |
248 | | IMMER_TRY { |
249 | | p->data()[idx] = std::move(value); |
250 | | *this = {p, size, capacity}; |
251 | | } |
252 | | IMMER_CATCH (...) { |
253 | | node_t::delete_n(p, size, capacity); |
254 | | IMMER_RETHROW; |
255 | | } |
256 | | } |
257 | | } |
258 | | |
259 | | template <typename Fn> |
260 | | with_capacity update(std::size_t idx, Fn&& op) const |
261 | 5.06k | { |
262 | 5.06k | auto p = node_t::copy_n(capacity, ptr, size); |
263 | 5.06k | IMMER_TRY { |
264 | 5.06k | auto& elem = p->data()[idx]; |
265 | 5.06k | elem = std::forward<Fn>(op)(std::move(elem)); |
266 | 5.06k | return {p, size, capacity}; |
267 | 5.06k | } |
268 | 5.06k | IMMER_CATCH (...) { |
269 | 0 | node_t::delete_n(p, size, capacity); |
270 | 0 | IMMER_RETHROW; |
271 | 0 | } |
272 | 5.06k | } |
273 | | |
274 | | template <typename Fn> |
275 | | void update_mut(edit_t e, std::size_t idx, Fn&& op) |
276 | 7.51k | { |
277 | 7.51k | if (ptr->can_mutate(e)) { |
278 | 7.27k | auto& elem = data()[idx]; |
279 | 7.27k | elem = std::forward<Fn>(op)(std::move(elem)); |
280 | 7.27k | } else { |
281 | 243 | auto p = node_t::copy_e(e, capacity, ptr, size); |
282 | 243 | IMMER_TRY { |
283 | 243 | auto& elem = p->data()[idx]; |
284 | 243 | elem = std::forward<Fn>(op)(std::move(elem)); |
285 | 243 | *this = {p, size, capacity}; |
286 | 243 | } |
287 | 243 | IMMER_CATCH (...) { |
288 | 0 | node_t::delete_n(p, size, capacity); |
289 | 0 | IMMER_RETHROW; |
290 | 0 | } |
291 | 243 | } |
292 | 7.51k | } array-gc.cpp:void immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::update_mut<LLVMFuzzerTestOneInput::$_4::operator()<fuzzer_input>(fuzzer_input&) const::{lambda(auto:1)#2}>(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned long, fuzzer_input&&) Line | Count | Source | 276 | 872 | { | 277 | 872 | if (ptr->can_mutate(e)) { | 278 | 629 | auto& elem = data()[idx]; | 279 | 629 | elem = std::forward<Fn>(op)(std::move(elem)); | 280 | 629 | } else { | 281 | 243 | auto p = node_t::copy_e(e, capacity, ptr, size); | 282 | 243 | IMMER_TRY { | 283 | 243 | auto& elem = p->data()[idx]; | 284 | 243 | elem = std::forward<Fn>(op)(std::move(elem)); | 285 | 243 | *this = {p, size, capacity}; | 286 | 243 | } | 287 | 243 | IMMER_CATCH (...) { | 288 | 0 | node_t::delete_n(p, size, capacity); | 289 | 0 | IMMER_RETHROW; | 290 | 0 | } | 291 | 243 | } | 292 | 872 | } |
array.cpp:void immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::update_mut<LLVMFuzzerTestOneInput::$_4::operator()<fuzzer_input>(fuzzer_input&) const::{lambda(auto:1)#2}>(immer::no_transience_policy::apply<immer::free_list_heap_policy<immer::cpp_heap, 1024ul> >::type::edit, unsigned long, fuzzer_input&&) Line | Count | Source | 276 | 6.64k | { | 277 | 6.64k | if (ptr->can_mutate(e)) { | 278 | 6.64k | auto& elem = data()[idx]; | 279 | 6.64k | elem = std::forward<Fn>(op)(std::move(elem)); | 280 | 6.64k | } else { | 281 | 0 | auto p = node_t::copy_e(e, capacity, ptr, size); | 282 | 0 | IMMER_TRY { | 283 | 0 | auto& elem = p->data()[idx]; | 284 | 0 | elem = std::forward<Fn>(op)(std::move(elem)); | 285 | 0 | *this = {p, size, capacity}; | 286 | 0 | } | 287 | 0 | IMMER_CATCH (...) { | 288 | 0 | node_t::delete_n(p, size, capacity); | 289 | 0 | IMMER_RETHROW; | 290 | 0 | } | 291 | 0 | } | 292 | 6.64k | } |
|
293 | | |
294 | | with_capacity take(std::size_t sz) const |
295 | 5.67k | { |
296 | 5.67k | assert(sz <= size); |
297 | 0 | auto cap = recommend_down(sz, capacity); |
298 | 5.67k | auto p = node_t::copy_n(cap, ptr, sz); |
299 | 5.67k | return {p, sz, cap}; |
300 | 5.67k | } |
301 | | |
302 | | void take_mut(edit_t e, std::size_t sz) |
303 | 5.47k | { |
304 | 5.47k | assert(sz <= size); |
305 | 5.47k | if (ptr->can_mutate(e)) { |
306 | 4.16k | detail::destroy_n(data() + size, size - sz); |
307 | 4.16k | size = sz; |
308 | 4.16k | } else { |
309 | 1.31k | auto cap = recommend_down(sz, capacity); |
310 | 1.31k | auto p = node_t::copy_e(e, cap, ptr, sz); |
311 | 1.31k | *this = {p, sz, cap}; |
312 | 1.31k | } |
313 | 5.47k | } immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::take_mut(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned long) Line | Count | Source | 303 | 3.19k | { | 304 | 3.19k | assert(sz <= size); | 305 | 3.19k | if (ptr->can_mutate(e)) { | 306 | 1.97k | detail::destroy_n(data() + size, size - sz); | 307 | 1.97k | size = sz; | 308 | 1.97k | } else { | 309 | 1.22k | auto cap = recommend_down(sz, capacity); | 310 | 1.22k | auto p = node_t::copy_e(e, cap, ptr, sz); | 311 | 1.22k | *this = {p, sz, cap}; | 312 | 1.22k | } | 313 | 3.19k | } |
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::take_mut(immer::no_transience_policy::apply<immer::free_list_heap_policy<immer::cpp_heap, 1024ul> >::type::edit, unsigned long) Line | Count | Source | 303 | 2.28k | { | 304 | 2.28k | assert(sz <= size); | 305 | 2.28k | if (ptr->can_mutate(e)) { | 306 | 2.18k | detail::destroy_n(data() + size, size - sz); | 307 | 2.18k | size = sz; | 308 | 2.18k | } else { | 309 | 93 | auto cap = recommend_down(sz, capacity); | 310 | 93 | auto p = node_t::copy_e(e, cap, ptr, sz); | 311 | 93 | *this = {p, sz, cap}; | 312 | 93 | } | 313 | 2.28k | } |
|
314 | | }; |
315 | | |
316 | | } // namespace arrays |
317 | | } // namespace detail |
318 | | } // namespace immer |