libtcspc C++ API
Streaming TCSPC and time tag data processing
Loading...
Searching...
No Matches
bucket.hpp
1/*
2 * This file is part of libtcspc
3 * Copyright 2019-2026 Board of Regents of the University of Wisconsin System
4 * SPDX-License-Identifier: MIT
5 */
6
7#pragma once
8
9#include "arg_wrappers.hpp"
10#include "errors.hpp"
11#include "introspect.hpp"
12#include "move_only_any.hpp"
13#include "processor.hpp"
14
15#include <algorithm>
16#include <cassert>
17#include <condition_variable>
18#include <cstddef>
19#include <functional>
20#include <limits>
21#include <memory>
22#include <mutex>
23#include <ostream>
24#include <span>
25#include <stdexcept>
26#include <type_traits>
27#include <typeinfo>
28#include <utility>
29#include <vector>
30
31namespace tcspc {
32
110template <typename T> class bucket {
111 struct owning_storage {
112 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
113 std::unique_ptr<T[]> p;
114
115 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
116 explicit owning_storage(std::unique_ptr<T[]> ptr)
117 : p(std::move(ptr)) {}
118 };
119
120 std::span<T> s;
121 internal::move_only_any store;
122
123 public:
127 bucket() noexcept = default;
128
136 template <typename S>
137 explicit bucket(std::span<T> span, S &&storage)
138 : s(span), store(std::forward<S>(storage)) {}
139
140 ~bucket() = default;
141
143 bucket(bucket const &other)
144 : store(std::invoke([&s = other.s] {
145 using TMut = std::remove_cv_t<T>;
146 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
147 std::unique_ptr<TMut[]> r(s.empty() ? nullptr
148 : new TMut[s.size()]);
149 std::copy(s.begin(), s.end(), r.get());
150 return internal::move_only_any(
151 std::in_place_type<owning_storage>, std::move(r));
152 })) {
153 T *ptr = internal::move_only_any_cast<owning_storage>(&store)->p.get();
154 s = {ptr, other.s.size()};
155 }
156
158 bucket(bucket &&other) noexcept = default;
159
161 auto operator=(bucket const &other) -> bucket & {
162 bucket t(other);
163 std::swap(*this, t);
164 return *this;
165 }
166
168 auto operator=(bucket &&other) noexcept -> bucket & = default;
169
170 // Equivalents of most of span's members follow. But many of the member
171 // functions are duplicated to work with a const bucket (because a const
172 // bucket has read-only data, unlike a const span).
173
175 using element_type = typename std::span<T>::element_type;
177 using value_type = typename std::span<T>::value_type;
179 using size_type = typename std::span<T>::size_type;
181 using difference_type = typename std::span<T>::difference_type;
183 using pointer = typename std::span<T>::pointer;
185 using const_pointer = typename std::span<T>::const_pointer;
187 using reference = typename std::span<T>::reference;
189 using const_reference = typename std::span<T>::const_reference;
191 using iterator = typename std::span<T>::iterator;
193 using const_iterator = typename std::span<T const>::iterator;
195 using reverse_iterator = typename std::span<T>::reverse_iterator;
198 typename std::span<T const>::reverse_iterator;
199
201 [[nodiscard]] constexpr auto begin() noexcept -> iterator {
202 return s.begin();
203 }
204
206 [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator {
207 return std::span<T const>(s).begin();
208 }
209
211 [[nodiscard]] constexpr auto begin() const noexcept -> const_iterator {
212 return cbegin();
213 }
214
216 [[nodiscard]] constexpr auto end() noexcept -> iterator { return s.end(); }
217
219 [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator {
220 return std::span<T const>(s).end();
221 }
222
224 [[nodiscard]] constexpr auto end() const noexcept -> const_iterator {
225 return cend();
226 }
227
229 [[nodiscard]] constexpr auto rbegin() noexcept -> reverse_iterator {
230 return s.rbegin();
231 }
232
234 [[nodiscard]] constexpr auto crbegin() const noexcept
236 return std::span<T const>(s).rbegin();
237 }
238
240 [[nodiscard]] constexpr auto rbegin() const noexcept
242 return crbegin();
243 }
244
246 [[nodiscard]] constexpr auto rend() noexcept -> reverse_iterator {
247 return s.rend();
248 }
249
251 [[nodiscard]] constexpr auto crend() const noexcept
253 return std::span<T const>(s).rend();
254 }
255
257 [[nodiscard]] constexpr auto rend() const noexcept
259 return crend();
260 }
261
263 [[nodiscard]] constexpr auto front() -> reference { return s.front(); }
264
266 [[nodiscard]] constexpr auto front() const -> const_reference {
267 return std::span<T const>(s).front();
268 }
269
271 [[nodiscard]] constexpr auto back() -> reference { return s.back(); }
272
274 [[nodiscard]] constexpr auto back() const -> const_reference {
275 return std::span<T const>(s).back();
276 }
277
279 [[nodiscard]] constexpr auto operator[](size_type idx) -> reference {
280 return s[idx];
281 }
282
284 [[nodiscard]] constexpr auto operator[](size_type idx) const
285 -> const_reference {
286 return s[idx];
287 }
288
290 [[nodiscard]] constexpr auto at(size_type pos) -> reference {
291 if (pos >= size())
292 throw std::out_of_range("bucket element index out of range");
293 return s[pos];
294 }
295
297 [[nodiscard]] constexpr auto at(size_type pos) const -> const_reference {
298 if (pos >= size())
299 throw std::out_of_range("bucket element index out of range");
300 return s[pos];
301 }
302
304 [[nodiscard]] constexpr auto data() noexcept -> pointer {
305 return s.data();
306 }
307
309 [[nodiscard]] constexpr auto data() const noexcept -> const_pointer {
310 return s.data();
311 }
312
314 [[nodiscard]] constexpr auto size() const noexcept -> size_type {
315 return s.size();
316 }
317
319 [[nodiscard]] constexpr auto size_bytes() const noexcept -> size_type {
320 return s.size_bytes();
321 }
322
324 [[nodiscard]] constexpr auto empty() const noexcept -> bool {
325 return s.empty();
326 }
327
329 [[nodiscard]] constexpr auto first(size_type count) -> std::span<T> {
330 return s.first(count);
331 }
332
334 [[nodiscard]] constexpr auto first(size_type count) const
335 -> std::span<T const> {
336 return std::span<T const>(s).first(count);
337 }
338
340 [[nodiscard]] constexpr auto last(size_type count) -> std::span<T> {
341 return s.last(count);
342 }
343
345 [[nodiscard]] constexpr auto last(size_type count) const
346 -> std::span<T const> {
347 return std::span<T const>(s).last(count);
348 }
349
351 [[nodiscard]] constexpr auto subspan(size_type offset,
352 size_type count = std::dynamic_extent)
353 -> std::span<T> {
354 return s.subspan(offset, count);
355 }
356
358 [[nodiscard]] constexpr auto
359 subspan(size_type offset, size_type count = std::dynamic_extent) const
360 -> std::span<T const> {
361 return std::span<T const>(s).subspan(offset, count);
362 }
363
364 // End of span member equivalents.
365
366 // We do not prevent access to storage of owning instance, but the value
367 // inside the move_only_any will not be accessible because owning_storage
368 // is a private type.
369
377 template <typename S>
378 [[nodiscard]] auto check_storage_type() const noexcept -> bool {
379 return store.type() == typeid(S);
380 }
381
392 template <typename S> [[nodiscard]] auto storage() const -> S const & {
393 return internal::move_only_any_cast<S const &>(store);
394 }
395
411 template <typename S> [[nodiscard]] auto extract_storage() -> S {
412 s = {};
413 S ret = internal::move_only_any_cast<S>(std::move(store));
414 store = {};
415 return ret;
416 }
417
428 void shrink(std::size_t start, std::size_t count = std::dynamic_extent) {
429 s = s.subspan(start, count);
430 }
431
432 // In contrast to span, bucket equality is deep equality.
433
439 friend constexpr auto operator==(bucket const &lhs, bucket const &rhs)
440 -> bool {
441 return lhs.s.size() == rhs.s.size() &&
442 std::equal(lhs.s.begin(), lhs.s.end(), rhs.s.begin());
443 }
444
446 friend auto operator<<(std::ostream &stream, bucket const &bkt)
447 -> std::ostream & {
448 static constexpr std::size_t num_to_print = 10;
449 auto const size = bkt.s.size();
450 stream << "bucket(size=" << size;
451 if constexpr (std::is_same_v<std::remove_cv_t<T>, std::byte>) {
452 for (std::size_t i = 0; i < std::min(size, num_to_print - 1); ++i)
453 stream << ", " << std::to_integer<int>(bkt.s[i]);
454 if (size > num_to_print)
455 stream << ", ...";
456 if (size >= num_to_print)
457 stream << ", " << std::to_integer<int>(bkt.s[size - 1]);
458 } else {
459 for (std::size_t i = 0; i < std::min(size, num_to_print - 1); ++i)
460 stream << ", " << bkt.s[i];
461 if (size > num_to_print)
462 stream << ", ...";
463 if (size >= num_to_print)
464 stream << ", " << bkt.s[size - 1];
465 }
466 return stream << ')';
467 }
468};
469
488template <typename T>
489[[nodiscard]] auto ad_hoc_bucket(std::span<T> s) -> bucket<T> {
490 struct ad_hoc_storage {};
491 return bucket<T>(s, ad_hoc_storage{});
492}
493
505template <typename T> struct bucket_source {
506 virtual ~bucket_source() = default;
507
517 virtual auto bucket_of_size(std::size_t size) -> bucket<T> = 0;
518
528 [[nodiscard]] virtual auto supports_shared_views() const noexcept -> bool {
529 return false;
530 }
531
565 [[nodiscard]] virtual auto
566 shared_view_of([[maybe_unused]] bucket<T> const &bkt) -> bucket<T const> {
567 throw std::logic_error(
568 "this bucket source does not support shared views");
569 }
570};
571
587template <typename T>
588class new_delete_bucket_source final : public bucket_source<T> {
589 new_delete_bucket_source() = default;
590
591 public:
593 static auto create() -> std::shared_ptr<bucket_source<T>> {
594 static std::shared_ptr<bucket_source<T>> instance(
595 new new_delete_bucket_source());
596 return instance;
597 }
598
600 auto bucket_of_size(std::size_t size) -> bucket<T> override {
601 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
602 std::unique_ptr<T[]> p(new T[size]);
603 return bucket<T>{std::span(p.get(), size), std::move(p)};
604 }
605};
606
623template <typename T>
624class sharable_new_delete_bucket_source final : public bucket_source<T> {
625 sharable_new_delete_bucket_source() = default;
626
627 public:
629 static auto create() -> std::shared_ptr<bucket_source<T>> {
630 static std::shared_ptr<bucket_source<T>> instance(
631 new sharable_new_delete_bucket_source());
632 return instance;
633 }
634
636 auto bucket_of_size(std::size_t size) -> bucket<T> override {
637 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
638 std::shared_ptr<T[]> p(new T[size]);
639 return bucket<T>{std::span(p.get(), size), std::move(p)};
640 }
641
643 [[nodiscard]] auto supports_shared_views() const noexcept
644 -> bool override {
645 return true;
646 }
647
649 [[nodiscard]] auto shared_view_of(bucket<T> const &bkt)
650 -> bucket<T const> override {
651 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
652 auto storage = bkt.template storage<std::shared_ptr<T[]>>();
653 return bucket<T const>{std::span<T const>(bkt), std::move(storage)};
654 }
655};
656
680template <typename T, bool Blocking = false, bool ClearRecycled = false>
681class recycling_bucket_source final
682 : public bucket_source<T>,
683 public std::enable_shared_from_this<
684 recycling_bucket_source<T, Blocking, ClearRecycled>> {
685 std::mutex mutex;
686 std::condition_variable not_empty_condition;
687 std::size_t max_buckets;
688 std::size_t max_recycled;
689 std::size_t bucket_count = 0;
690 std::vector<std::unique_ptr<std::vector<T>>> recyclable;
691
692 struct bucket_storage {
693 std::shared_ptr<recycling_bucket_source> source;
694 std::unique_ptr<std::vector<T>> storage;
695
696 ~bucket_storage() {
697 if (not source)
698 return;
699
700 assert(storage);
701
702 // If "large" bucket, release the underlying storage (but do go on
703 // to "recycle", so that a thread waiting on bucket_of_size() will
704 // get a bucket).
705 if (source->max_recycled > 0 &&
706 storage->size() > source->max_recycled)
707 *storage = std::vector<T>();
708
709 if constexpr (ClearRecycled)
710 storage->clear();
711
712 {
713 auto const lock = std::lock_guard(source->mutex);
714 source->recyclable.push_back(std::move(storage));
715 }
716
717 if constexpr (Blocking) {
718 // Is it safe to wake up the source when this bucket_storage
719 // might be the last thing holding on to it? Yes, because if
720 // that is the case there is no thread waiting on the source.
721 source->not_empty_condition.notify_one();
722 }
723 }
724
725 explicit bucket_storage(
726 std::shared_ptr<recycling_bucket_source> source,
727 std::unique_ptr<std::vector<T>> &&storage)
728 : source(std::move(source)), storage(std::move(storage)) {}
729
730 bucket_storage(bucket_storage const &) = delete;
731 auto operator=(bucket_storage const &) = delete;
732
733 bucket_storage(bucket_storage &&) noexcept = default;
734 auto operator=(bucket_storage &&) noexcept
735 -> bucket_storage & = default;
736 };
737
738 explicit recycling_bucket_source(
739 arg::max_bucket_count<> max_bucket_count,
740 arg::max_recycled_size<> max_recycled_size)
741 : max_buckets(max_bucket_count.value),
742 max_recycled(max_recycled_size.value) {}
743
744 public:
754 static auto create(
755 arg::max_bucket_count<> max_bucket_count =
756 arg::max_bucket_count{std::numeric_limits<std::size_t>::max()},
758 0}) -> std::shared_ptr<bucket_source<T>> {
759 return std::shared_ptr<recycling_bucket_source>(
760 new recycling_bucket_source(max_bucket_count, max_recycled_size));
761 }
762
773 auto bucket_of_size(std::size_t size) -> bucket<T> override {
774 std::unique_ptr<std::vector<T>> p;
775 {
776 auto lock = std::unique_lock(mutex);
777 if (recyclable.empty() && bucket_count < max_buckets) {
778 ++bucket_count;
779 } else {
780 if constexpr (Blocking) {
781 not_empty_condition.wait(
782 lock, [&] { return not recyclable.empty(); });
783 } else if (recyclable.empty()) {
785 "recycling bucket source exhausted");
786 }
787 p = std::move(recyclable.back());
788 recyclable.pop_back();
789 }
790 }
791 if (not p)
792 p = std::make_unique<std::vector<T>>();
793 p->resize(size);
794 auto const spn = std::span(p->data(), p->size());
795 return bucket<T>{
796 spn, bucket_storage(this->shared_from_this(), std::move(p))};
797 }
798};
799
810template <typename T, bool Blocking = false, bool ClearRecycled = false>
811class sharable_recycling_bucket_source final
812 : public bucket_source<T>,
813 public std::enable_shared_from_this<
814 sharable_recycling_bucket_source<T, Blocking, ClearRecycled>> {
815 std::mutex mutex;
816 std::condition_variable not_empty_condition;
817 std::size_t max_buckets;
818 std::size_t max_recycled;
819 std::size_t bucket_count = 0;
820 std::vector<std::unique_ptr<std::vector<T>>> recyclable;
821
822 // Wrap storage in private type to forbid observation/extraction.
823 struct bucket_storage {
824 std::shared_ptr<std::vector<T>> storage; // With custom deleter.
825 };
826
827 explicit sharable_recycling_bucket_source(
828 arg::max_bucket_count<> max_bucket_count,
829 arg::max_recycled_size<> max_recycled_size)
830 : max_buckets(max_bucket_count.value),
831 max_recycled(max_recycled_size.value) {}
832
833 public:
839 static auto create(
840 arg::max_bucket_count<> max_bucket_count =
841 arg::max_bucket_count{std::numeric_limits<std::size_t>::max()},
843 0}) -> std::shared_ptr<bucket_source<T>> {
844 return std::shared_ptr<sharable_recycling_bucket_source>(
845 new sharable_recycling_bucket_source(max_bucket_count,
846 max_recycled_size));
847 }
848
854 auto bucket_of_size(std::size_t size) -> bucket<T> override {
855 std::unique_ptr<std::vector<T>> p;
856 {
857 auto lock = std::unique_lock(mutex);
858 if (recyclable.empty() && bucket_count < max_buckets) {
859 ++bucket_count;
860 } else {
861 if constexpr (Blocking) {
862 not_empty_condition.wait(
863 lock, [&] { return not recyclable.empty(); });
864 } else if (recyclable.empty()) {
866 "sharable recycling bucket source exhausted");
867 }
868 p = std::move(recyclable.back());
869 recyclable.pop_back();
870 }
871 }
872 if (not p)
873 p = std::make_unique<std::vector<T>>();
874 p->resize(size);
875 auto const spn = std::span(*p);
876 std::shared_ptr<std::vector<T>> shptr{
877 p.release(),
878 [self = this->shared_from_this()](std::vector<T> *pv) {
879 if (not pv)
880 return;
881 if (self->max_recycled > 0 && pv->size() > self->max_recycled)
882 *pv = std::vector<T>();
883 if constexpr (ClearRecycled)
884 pv->clear();
885 {
886 auto const lock = std::lock_guard(self->mutex);
887 self->recyclable.emplace_back(pv);
888 }
889 if constexpr (Blocking)
890 self->not_empty_condition.notify_one();
891 }
892
893 };
894 return bucket<T>{spn, bucket_storage{shptr}};
895 }
896
898 [[nodiscard]] auto supports_shared_views() const noexcept
899 -> bool override {
900 return true;
901 }
902
904 [[nodiscard]] auto shared_view_of(bucket<T> const &bkt)
905 -> bucket<T const> override {
906 auto storage = bkt.template storage<bucket_storage>();
907 return bucket<T const>{std::span<T const>(bkt), std::move(storage)};
908 }
909};
910
911namespace internal {
912
913template <typename Event, typename Downstream> class extract_bucket {
914 static_assert(
915 processor<Downstream, decltype(std::declval<Event>().data_bucket)>);
916
917 Downstream downstream;
918
919 public:
920 explicit extract_bucket(Downstream downstream)
921 : downstream(std::move(downstream)) {}
922
923 [[nodiscard]] auto introspect_node() const -> processor_info {
924 return processor_info(this, "extract_bucket");
925 }
926
927 [[nodiscard]] auto introspect_graph() const -> processor_graph {
928 return downstream.introspect_graph().push_entry_point(this);
929 }
930
931 void handle(Event const &event) { downstream.handle(event.data_bucket); }
932
933 void handle(Event &&event) {
934 downstream.handle(std::move(event).data_bucket);
935 }
936
937 void flush() { downstream.flush(); }
938};
939
940} // namespace internal
941
960template <typename Event, typename Downstream>
961auto extract_bucket(Downstream downstream) {
962 return internal::extract_bucket<Event, Downstream>(std::move(downstream));
963}
964
965} // namespace tcspc
Value-semantic container for array data allowing use of custom storage.
Definition bucket.hpp:110
constexpr auto end() noexcept -> iterator
Return an iterator to the end.
Definition bucket.hpp:216
constexpr auto rend() noexcept -> reverse_iterator
Return a reverse iterator to the end.
Definition bucket.hpp:246
constexpr auto rbegin() noexcept -> reverse_iterator
Return a reverse iterator to the beginning.
Definition bucket.hpp:229
constexpr auto operator[](size_type idx) -> reference
Return an element without bounds checking.
Definition bucket.hpp:279
auto storage() const -> S const &
Observe the underlying storage.
Definition bucket.hpp:392
typename std::span< T >::iterator iterator
Iterator type.
Definition bucket.hpp:191
constexpr auto crbegin() const noexcept -> const_reverse_iterator
Return a reverse iterator to the beginning.
Definition bucket.hpp:234
typename std::span< T >::size_type size_type
Size type.
Definition bucket.hpp:179
constexpr auto empty() const noexcept -> bool
Return whether this bucket is empty.
Definition bucket.hpp:324
constexpr auto at(size_type pos) const -> const_reference
Return an element with bounds checking.
Definition bucket.hpp:297
constexpr auto rbegin() const noexcept -> const_reverse_iterator
Return a reverse iterator to the beginning.
Definition bucket.hpp:240
friend constexpr auto operator==(bucket const &lhs, bucket const &rhs) -> bool
Equality comparison operator.
Definition bucket.hpp:439
constexpr auto rend() const noexcept -> const_reverse_iterator
Return a reverse iterator to the end.
Definition bucket.hpp:257
constexpr auto operator[](size_type idx) const -> const_reference
Return an element without bounds checking.
Definition bucket.hpp:284
typename std::span< T >::element_type element_type
Element type.
Definition bucket.hpp:175
constexpr auto subspan(size_type offset, size_type count=std::dynamic_extent) const -> std::span< T const >
Return the span of the given range of elements.
Definition bucket.hpp:359
constexpr auto at(size_type pos) -> reference
Return an element with bounds checking.
Definition bucket.hpp:290
constexpr auto last(size_type count) -> std::span< T >
Return the span of the last count elements.
Definition bucket.hpp:340
bucket(bucket &&other) noexcept=default
Move constructor.
typename std::span< T >::const_reference const_reference
Element const reference type.
Definition bucket.hpp:189
typename std::span< T >::const_pointer const_pointer
Element const pointer type.
Definition bucket.hpp:185
constexpr auto back() const -> const_reference
Return the last element.
Definition bucket.hpp:274
constexpr auto front() const -> const_reference
Return the first element.
Definition bucket.hpp:266
auto operator=(bucket &&other) noexcept -> bucket &=default
Move assignment operator.
auto operator=(bucket const &other) -> bucket &
Copy assignment operator (allocates new private storage).
Definition bucket.hpp:161
constexpr auto end() const noexcept -> const_iterator
Return an iterator to the end.
Definition bucket.hpp:224
constexpr auto begin() const noexcept -> const_iterator
Return an iterator to the beginning.
Definition bucket.hpp:211
typename std::span< T >::difference_type difference_type
Difference type.
Definition bucket.hpp:181
typename std::span< T >::reverse_iterator reverse_iterator
Reverse iterator type.
Definition bucket.hpp:195
typename std::span< T const >::reverse_iterator const_reverse_iterator
Const reverse iterator type.
Definition bucket.hpp:197
constexpr auto cend() const noexcept -> const_iterator
Return an iterator to the end.
Definition bucket.hpp:219
bucket(bucket const &other)
Copy constructor (allocates new private storage).
Definition bucket.hpp:143
constexpr auto data() noexcept -> pointer
Return the address of the data.
Definition bucket.hpp:304
constexpr auto back() -> reference
Return the last element.
Definition bucket.hpp:271
auto extract_storage() -> S
Extract the underlying storage.
Definition bucket.hpp:411
void shrink(std::size_t start, std::size_t count=std::dynamic_extent)
Shrink the span of the bucket data.
Definition bucket.hpp:428
typename std::span< T >::pointer pointer
Element pointer type.
Definition bucket.hpp:183
bucket() noexcept=default
Construct an empty bucket.
constexpr auto size() const noexcept -> size_type
Return the number of data elements in this bucket.
Definition bucket.hpp:314
constexpr auto last(size_type count) const -> std::span< T const >
Return the span of the last count elements.
Definition bucket.hpp:345
constexpr auto begin() noexcept -> iterator
Return an iterator to the beginning.
Definition bucket.hpp:201
auto check_storage_type() const noexcept -> bool
Check if the underlying storage is of a given type.
Definition bucket.hpp:378
constexpr auto crend() const noexcept -> const_reverse_iterator
Return a reverse iterator to the end.
Definition bucket.hpp:251
constexpr auto front() -> reference
Return the first element.
Definition bucket.hpp:263
constexpr auto subspan(size_type offset, size_type count=std::dynamic_extent) -> std::span< T >
Return the span of the given range of elements.
Definition bucket.hpp:351
typename std::span< T const >::iterator const_iterator
Const iterator type.
Definition bucket.hpp:193
constexpr auto data() const noexcept -> const_pointer
Return the address of the data.
Definition bucket.hpp:309
constexpr auto cbegin() const noexcept -> const_iterator
Return an iterator to the beginning.
Definition bucket.hpp:206
friend auto operator<<(std::ostream &stream, bucket const &bkt) -> std::ostream &
Stream insertion operator.
Definition bucket.hpp:446
typename std::span< T >::value_type value_type
Value type.
Definition bucket.hpp:177
constexpr auto first(size_type count) const -> std::span< T const >
Return the span of the first count elements.
Definition bucket.hpp:334
constexpr auto first(size_type count) -> std::span< T >
Return the span of the first count elements.
Definition bucket.hpp:329
typename std::span< T >::reference reference
Element reference type.
Definition bucket.hpp:187
constexpr auto size_bytes() const noexcept -> size_type
Return the size of this bucket's data in bytes.
Definition bucket.hpp:319
Error thrown when buffer capacity has been exhausted.
Definition errors.hpp:84
static auto create() -> std::shared_ptr< bucket_source< T > >
Create an instance.
Definition bucket.hpp:593
auto bucket_of_size(std::size_t size) -> bucket< T > override
Implements bucket source requirement.
Definition bucket.hpp:600
auto bucket_of_size(std::size_t size) -> bucket< T > override
Implements bucket source requirement.
Definition bucket.hpp:773
static auto create(arg::max_bucket_count<> max_bucket_count=arg::max_bucket_count{std::numeric_limits< std::size_t >::max()}, arg::max_recycled_size<> max_recycled_size=arg::max_recycled_size<>{ 0}) -> std::shared_ptr< bucket_source< T > >
Create an instance.
Definition bucket.hpp:754
auto bucket_of_size(std::size_t size) -> bucket< T > override
Implements bucket source requirement.
Definition bucket.hpp:636
auto supports_shared_views() const noexcept -> bool override
Implements sharable bucket source requirement.
Definition bucket.hpp:643
static auto create() -> std::shared_ptr< bucket_source< T > >
Create an instance.
Definition bucket.hpp:629
auto shared_view_of(bucket< T > const &bkt) -> bucket< T const > override
Implements sharable bucket source requirement.
Definition bucket.hpp:649
auto supports_shared_views() const noexcept -> bool override
Implements sharable bucket source requirement.
Definition bucket.hpp:898
auto shared_view_of(bucket< T > const &bkt) -> bucket< T const > override
Implements sharable bucket source requirement.
Definition bucket.hpp:904
auto bucket_of_size(std::size_t size) -> bucket< T > override
Implements bucket source requirement.
Definition bucket.hpp:854
static auto create(arg::max_bucket_count<> max_bucket_count=arg::max_bucket_count{std::numeric_limits< std::size_t >::max()}, arg::max_recycled_size<> max_recycled_size=arg::max_recycled_size<>{ 0}) -> std::shared_ptr< bucket_source< T > >
Create an instance.
Definition bucket.hpp:839
auto ad_hoc_bucket(std::span< T > s) -> bucket< T >
Create a tcspc::bucket referencing a span.
Definition bucket.hpp:489
auto extract_bucket(Downstream downstream)
Create a processor that extracts the bucket carried by an event.
Definition bucket.hpp:961
auto count(access_tracker< count_access > &&tracker, Downstream downstream)
Create a processor that counts events of a given type.
Definition count.hpp:313
libtcspc namespace.
Definition acquire.hpp:29
Function argument wrapper for maximum bucket count.
Definition arg_wrappers.hpp:227
T value
The argument value.
Definition arg_wrappers.hpp:229
Function argument wrapper for maximum recycled size.
Definition arg_wrappers.hpp:297
T value
The argument value.
Definition arg_wrappers.hpp:299
Abstract base class for polymorphic bucket sources.
Definition bucket.hpp:505
virtual auto bucket_of_size(std::size_t size) -> bucket< T >=0
Create a bucket of size elements of type T.
virtual auto shared_view_of(bucket< T > const &bkt) -> bucket< T const >
Create a shared view bucket that is a read-only view of the given bucket but may outlive the original...
Definition bucket.hpp:566
virtual auto supports_shared_views() const noexcept -> bool
Return whether this bucket source is a sharable bucket source.
Definition bucket.hpp:528