26template<
typename T,
bool CheckNoneLeft>
34 std::vector<VecDeque<T>>
real;
37 std::vector<std::deque<T>>
sim;
47 if (
s.size() == 0)
return;
50 for (
size_t i = 0; i <
s.size(); ++i) {
57 unsigned idx =
real.empty() ? 0 : provider.ConsumeIntegralInRange<
unsigned>(0,
real.size() - 1);
111 sim.emplace_back(
sim[idx]);
117 real.emplace_back(std::move(copy));
118 sim.emplace_back(
sim[idx]);
138 real[idx] = std::move(copy);
171 real[idx].shrink_to_fit();
178 tmp =
T(rng.rand64());
194 tmp =
T(rng.rand64());
198 real[idx].push_back(std::move(*
tmp));
213 sim[idx].emplace_back(seed);
214 real[idx].emplace_back(seed);
226 tmp =
T(rng.rand64());
230 sim[idx].push_front(*
tmp);
242 tmp =
T(rng.rand64());
245 sim[idx].push_front(*
tmp);
246 real[idx].push_front(std::move(*
tmp));
261 sim[idx].emplace_front(seed);
262 real[idx].emplace_front(seed);
274 tmp =
T(rng.rand64());
278 real[idx].front() = std::move(*
tmp);
284 tmp =
T(rng.rand64());
294 tmp =
T(rng.rand64());
295 size_t pos = provider.ConsumeIntegralInRange<
size_t>(0,
sim[idx].size() - 1);
299 real[idx][pos] = std::move(*
tmp);
307 sim[idx].pop_front();
308 real[idx].pop_front();
317 real[idx].pop_back();
325 for (
unsigned i = 0; i <
sim.size(); ++i) {
330 for (
unsigned j = 0;
j <
sim.size(); ++
j) {
350 static_assert(Size > 0);
357 using track_map_type = std::map<const TrackedObj<Size>*, std::optional<uint64_t>>;
362 static inline track_map_type g_tracker;
368 typename track_map_type::iterator m_track_entry[Size];
372 auto it = g_tracker.find(
this);
373 for (
size_t i = 0; i < Size; ++i) {
374 assert(m_track_entry[i] == it);
381 auto [it,
inserted] = g_tracker.emplace(
this, std::nullopt);
383 for (
size_t i = 0; i < Size; ++i) {
384 m_track_entry[i] = it;
391 assert(m_track_entry[0] != g_tracker.end());
392 g_tracker.erase(m_track_entry[0]);
393 for (
size_t i = 0; i < Size; ++i) {
394 m_track_entry[i] = g_tracker.end();
399 std::optional<uint64_t>&
Deref()
402 assert(m_track_entry[0] != g_tracker.end());
403 return m_track_entry[0]->second;
407 const std::optional<uint64_t>&
Deref()
const
410 assert(m_track_entry[0] != g_tracker.end());
411 return m_track_entry[0]->second;
416 TrackedObj() { Register(); }
424 TrackedObj(
const TrackedObj& other)
427 Deref() = other.Deref();
430 TrackedObj(TrackedObj&& other)
433 Deref() = other.Deref();
434 other.Deref() = std::nullopt;
437 TrackedObj& operator=(
const TrackedObj& other)
439 if (
this == &other)
return *
this;
440 Deref() = other.Deref();
444 TrackedObj& operator=(TrackedObj&& other)
446 if (
this == &other)
return *
this;
447 Deref() = other.Deref();
448 other.Deref() = std::nullopt;
452 friend bool operator==(
const TrackedObj&
a,
const TrackedObj& b)
454 return a.Deref() == b.Deref();
457 friend std::strong_ordering operator<=>(
const TrackedObj&
a,
const TrackedObj& b)
461 if (!
a.Deref().has_value() || !b.Deref().has_value()) {
462 return a.Deref().has_value() <=> b.Deref().has_value();
464 return *
a.Deref() <=> *b.Deref();
469 assert(g_tracker.empty());
478 static_assert(std::is_trivially_copyable_v<uint32_t>);
479 static_assert(std::is_trivially_destructible_v<uint64_t>);
486 static_assert(!std::is_trivially_copyable_v<TrackedObj<3>>);
487 static_assert(!std::is_trivially_destructible_v<TrackedObj<17>>);
Data structure largely mimicking std::deque, but using single preallocated ring buffer.
bool empty() const noexcept
Test whether the contents of this deque is empty.
size_t size() const noexcept
Get the number of elements in this deque.
T & front() noexcept
Get a mutable reference to the first element of the deque.
size_t capacity() const noexcept
Get the capacity of this deque (maximum size it can have without reallocating).
T & back() noexcept
Get a mutable reference to the last element of the deque.
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
#define T(expected, seed, data)
bool operator==(const CNetAddr &a, const CNetAddr &b)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.