Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
87 lines
2.2 KiB
C++
87 lines
2.2 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup bli
|
|
*
|
|
* A `blender::Pool` allows fast allocation and deallocation of many elements of the same type.
|
|
*
|
|
* It is compatible with types that are not movable.
|
|
*
|
|
* Freed elements memory will be reused by next allocations.
|
|
* Elements are allocated in chunks to reduce memory fragmentation and avoid reallocation.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BLI_stack.hh"
|
|
#include "BLI_utility_mixins.hh"
|
|
#include "BLI_vector.hh"
|
|
|
|
namespace blender {
|
|
|
|
template<typename T, int64_t ChunkLen = 64> class Pool : NonCopyable {
|
|
private:
|
|
using Chunk = TypedBuffer<T, ChunkLen>;
|
|
|
|
/** Allocated item buffer. */
|
|
Vector<std::unique_ptr<Chunk>> values_;
|
|
/** List of freed elements to be use for the next allocations. A Stack is best here to avoid
|
|
* overhead when growing the free list. It also offers better cache performance than a queue
|
|
* since last added entries will be reused first. */
|
|
Stack<T *, 0> free_list_;
|
|
|
|
public:
|
|
~Pool()
|
|
{
|
|
/* All elements need to be freed before freeing the pool. */
|
|
BLI_assert(this->size() == 0);
|
|
}
|
|
|
|
/**
|
|
* Construct an object inside this pool's memory.
|
|
*/
|
|
template<typename... ForwardT> T &construct(ForwardT &&...value)
|
|
{
|
|
if (free_list_.is_empty()) {
|
|
values_.append(std::make_unique<Chunk>());
|
|
T *chunk_start = values_.last()->ptr();
|
|
for (auto i : IndexRange(ChunkLen)) {
|
|
free_list_.push(chunk_start + i);
|
|
}
|
|
}
|
|
T *ptr = free_list_.pop();
|
|
new (ptr) T(std::forward<ForwardT>(value)...);
|
|
return *ptr;
|
|
}
|
|
|
|
/**
|
|
* Destroy the given element inside this memory pool. Memory will be reused by next element
|
|
* construction. This invokes undefined behavior if the item is not from this pool.
|
|
*/
|
|
void destruct(T &value)
|
|
{
|
|
value.~T();
|
|
free_list_.push(&value);
|
|
}
|
|
|
|
/**
|
|
* Return the number of constructed elements in this pool.
|
|
*/
|
|
int64_t size() const
|
|
{
|
|
return values_.size() * ChunkLen - free_list_.size();
|
|
}
|
|
|
|
/**
|
|
* Returns true when the pool contains no elements, otherwise false.
|
|
*/
|
|
bool is_empty() const
|
|
{
|
|
return this->size() == 0;
|
|
}
|
|
};
|
|
|
|
} // namespace blender
|