Grok 20.3.2
SlabPool.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19#include <cstdint>
20#include <mutex>
21#include <queue>
22#include <stdexcept>
23
24namespace grk
25{
26
35{
36public:
44 SlabPool(size_t numSlots, size_t slotSize)
45 : numSlots_(numSlots), slotSize_(slotSize), slabSize_(numSlots * slotSize)
46 {
47 if(numSlots == 0)
48 throw std::invalid_argument("SlabPool: numSlots must be non-zero");
49 if(slotSize == 0)
50 throw std::invalid_argument("SlabPool: slotSize must be non-zero");
51
52 slab_ = std::make_unique<uint8_t[]>(slabSize_);
53 if(!slab_)
54 throw std::bad_alloc();
55
56 // Initialize free list with all slots
57 for(size_t i = 0; i < numSlots_; ++i)
58 {
59 freeBuffers_.push(&slab_[i * slotSize_]);
60 }
61 }
62
66 SlabPool(const SlabPool&) = delete;
67
71 SlabPool& operator=(const SlabPool&) = delete;
72
76 SlabPool(SlabPool&& other) noexcept
77 : numSlots_(other.numSlots_), slotSize_(other.slotSize_), slabSize_(other.slabSize_),
78 slab_(std::move(other.slab_))
79 {
80 std::lock_guard<std::mutex> lock(other.mutex_);
81 freeBuffers_ = std::move(other.freeBuffers_);
82 other.numSlots_ = 0;
83 other.slotSize_ = 0;
84 other.slabSize_ = 0;
85 }
86
90 SlabPool& operator=(SlabPool&& other) noexcept
91 {
92 if(this != &other)
93 {
94 std::lock_guard<std::mutex> lock(mutex_);
95 std::lock_guard<std::mutex> otherLock(other.mutex_);
96 numSlots_ = other.numSlots_;
97 slotSize_ = other.slotSize_;
98 slabSize_ = other.slabSize_;
99 slab_ = std::move(other.slab_);
100 freeBuffers_ = std::move(other.freeBuffers_);
101 other.numSlots_ = 0;
102 other.slotSize_ = 0;
103 other.slabSize_ = 0;
104 }
105 return *this;
106 }
107
111 ~SlabPool() = default;
112
118 uint8_t* allocate()
119 {
120 std::lock_guard<std::mutex> lock(mutex_);
121 if(freeBuffers_.empty())
122 throw std::runtime_error("SlabPool: No free buffers available");
123 uint8_t* buffer = freeBuffers_.front();
124 freeBuffers_.pop();
125 return buffer;
126 }
127
132 void recycle(uint8_t* buffer)
133 {
134 if(!buffer)
135 return;
136
137 std::lock_guard<std::mutex> lock(mutex_);
138 // Use uintptr_t to avoid sign issues with ptrdiff_t
139 auto slabBase = reinterpret_cast<std::uintptr_t>(slab_.get());
140 auto bufferAddr = reinterpret_cast<std::uintptr_t>(buffer);
141 std::uintptr_t offset = bufferAddr - slabBase;
142
143 // Validate buffer is within slab and aligned to a slot
144 if(offset < slabSize_ && (offset % slotSize_) == 0)
145 {
146 freeBuffers_.push(buffer);
147 }
148 // Silently ignore invalid buffers (or log/throw if desired)
149 }
150
155 size_t freeCount() const
156 {
157 std::lock_guard<std::mutex> lock(mutex_);
158 return freeBuffers_.size();
159 }
160
165 size_t totalSlots() const
166 {
167 return numSlots_;
168 }
169
174 size_t slotSize() const
175 {
176 return slotSize_;
177 }
178
183 size_t slabSize() const
184 {
185 return slabSize_;
186 }
187
188private:
189 size_t numSlots_; // Total number of slots
190 size_t slotSize_; // Size of each slot in bytes
191 size_t slabSize_; // Total size of the slab in bytes
192 std::unique_ptr<uint8_t[]> slab_; // Contiguous slab memory
193 mutable std::mutex mutex_; // Mutex for thread-safe access
194 std::queue<uint8_t*> freeBuffers_; // Free list of available buffers
195};
196
197} // namespace grk
size_t slabSize() const
Returns the total size of the slab in bytes.
Definition SlabPool.h:183
uint8_t * allocate()
Allocates a buffer from the pool.
Definition SlabPool.h:118
std::mutex mutex_
Definition SlabPool.h:193
SlabPool(SlabPool &&other) noexcept
Move constructor for transferring ownership.
Definition SlabPool.h:76
std::unique_ptr< uint8_t[]> slab_
Definition SlabPool.h:192
SlabPool & operator=(SlabPool &&other) noexcept
Move assignment operator for transferring ownership.
Definition SlabPool.h:90
SlabPool & operator=(const SlabPool &)=delete
Deleted assignment operator to prevent copying.
size_t totalSlots() const
Returns the total number of slots in the pool.
Definition SlabPool.h:165
size_t freeCount() const
Returns the number of free buffers currently available.
Definition SlabPool.h:155
void recycle(uint8_t *buffer)
Returns a buffer to the pool for reuse.
Definition SlabPool.h:132
std::queue< uint8_t * > freeBuffers_
Definition SlabPool.h:194
size_t slotSize_
Definition SlabPool.h:190
SlabPool(size_t numSlots, size_t slotSize)
Constructs a slab pool with a specified number of slots and slot size.
Definition SlabPool.h:44
size_t slotSize() const
Returns the size of each slot in bytes.
Definition SlabPool.h:174
~SlabPool()=default
Destructor, frees the slab memory.
size_t numSlots_
Definition SlabPool.h:189
SlabPool(const SlabPool &)=delete
Deleted copy constructor to prevent copying.
size_t slabSize_
Definition SlabPool.h:191
ResWindow.
Definition CompressedChunkCache.h:36