Project
Loading...
Searching...
No Matches
SlabBumpAllocator.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include <oneapi/tbb/blocked_range.h>
15#include <oneapi/tbb/enumerable_thread_specific.h>
16#include <oneapi/tbb/parallel_for.h>
17
19{
20
21namespace detail
22{
23
25 Impl(void* context_, Factory factory_, Deleter deleter_)
26 : context{context_}, factory{factory_}, deleter{deleter_}, values{[this] { return factory(context); }}
27 {
28 }
29
31 {
32 for (void* value : values) {
33 deleter(value);
34 }
35 }
36
37 void* context;
40 tbb::enumerable_thread_specific<void*> values;
41};
42
43ThreadLocalStorage::ThreadLocalStorage(void* context, Factory factory, Deleter deleter)
44 : mImpl{std::make_unique<Impl>(context, factory, deleter)}
45{
46}
47
49
51{
52 return mImpl->values.local();
53}
54
55std::vector<void*> ThreadLocalStorage::values() const
56{
57 return {mImpl->values.begin(), mImpl->values.end()};
58}
59
60void parallelFor(size_t begin, size_t end, size_t grainSize, void* context, ParallelForBody body)
61{
62 tbb::parallel_for(tbb::blocked_range<size_t>{begin, end, grainSize}, [context, body](const tbb::blocked_range<size_t>& range) {
63 body(context, range.begin(), range.end());
64 });
65}
66
67} // namespace detail
68
69SlabBumpAllocator::SlabBumpAllocator(size_t capacity, size_t slab) noexcept
70 : mCapacity{capacity}, mSlab{slab ? slab : size_t{1}}
71{
72}
73
75{
76 if (mExhausted.load(std::memory_order_relaxed)) {
77 return {};
78 }
79 const size_t base = mCursor.fetch_add(mSlab, std::memory_order_relaxed);
80 if (base >= mCapacity) {
81 mExhausted.store(true, std::memory_order_relaxed);
82 return {};
83 }
84 return {.base = base, .n = std::min(mSlab, mCapacity - base)};
85}
86
87size_t SlabBumpAllocator::watermark() const noexcept
88{
89 return std::min(mCursor.load(std::memory_order_relaxed), mCapacity);
90}
91
92size_t SlabBumpAllocator::suggestSlab(size_t capacity, int nThreads, size_t minSlab, size_t maxSlab) noexcept
93{
94 const size_t threads = static_cast<size_t>(std::max(1, nThreads));
95 const size_t fairShare = std::max<size_t>(1, capacity / threads);
96 return std::clamp(std::max<size_t>(1, capacity / (8 * threads)),
97 std::min(minSlab, fairShare),
98 std::min(maxSlab, fairShare));
99}
100
101void SlabBumpAllocator::resetCapacity(size_t capacity) noexcept
102{
103 assert(mCursor.load(std::memory_order_relaxed) == 0);
104 mCapacity = capacity;
105 mExhausted.store(capacity == 0, std::memory_order_relaxed);
106}
107
108} // namespace o2::itsmft::tracking
Lock-free slot allocator and single-pass sink.
void resetCapacity(size_t capacity) noexcept
static size_t suggestSlab(size_t capacity, int nThreads, size_t minSlab=256, size_t maxSlab=4096) noexcept
SlabBumpAllocator(size_t capacity, size_t slab) noexcept
GLuint GLuint end
Definition glcorearb.h:469
GLenum GLint * range
Definition glcorearb.h:1899
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLenum GLsizei GLsizei GLint * values
Definition glcorearb.h:1576
void parallelFor(size_t begin, size_t end, size_t grainSize, void *context, ParallelForBody body)
void(*)(void *, size_t, size_t) ParallelForBody
tbb::enumerable_thread_specific< void * > values
Impl(void *context_, Factory factory_, Deleter deleter_)