Files
test/source/blender/blenlib/BLI_allocator.hh
Campbell Barton e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
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.
2023-08-16 00:20:26 +10:00

90 lines
2.8 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*
* An `Allocator` can allocate and deallocate memory. It is used by containers such as
* blender::Vector. The allocators defined in this file do not work with standard library
* containers such as std::vector.
*
* Every allocator has to implement two methods:
* void *allocate(size_t size, size_t alignment, const char *name);
* void deallocate(void *ptr);
*
* We don't use the std::allocator interface, because it does more than is really necessary for an
* allocator and has some other quirks. It mixes the concepts of allocation and construction. It is
* essentially forced to be a template, even though the allocator should not care about the type.
* Also see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#std_allocator. Some
* of these aspects have been improved in new versions of C++, so we might have to reevaluate the
* strategy later on.
*
* The allocator interface dictated by this file is very simplistic, but for now that is all we
* need. More complexity can be added when it seems necessary.
*/
#include <algorithm>
#include <stdlib.h>
#include "MEM_guardedalloc.h"
#include "BLI_math_base.h"
#include "BLI_utildefines.h"
namespace blender {
/**
* Use Blender's guarded allocator (aka MEM_*). This should always be used except there is a
* good reason not to use it.
*/
class GuardedAllocator {
public:
void *allocate(size_t size, size_t alignment, const char *name)
{
/* Should we use MEM_mallocN, when alignment is small? If yes, how small must alignment be? */
return MEM_mallocN_aligned(size, alignment, name);
}
void deallocate(void *ptr)
{
MEM_freeN(ptr);
}
};
/**
* This is a wrapper around malloc/free. Only use this when the GuardedAllocator cannot be
* used. This can be the case when the allocated memory might live longer than Blender's
* allocator. For example, when the memory is owned by a static variable.
*/
class RawAllocator {
private:
struct MemHead {
int offset;
};
public:
void *allocate(size_t size, size_t alignment, const char * /*name*/)
{
BLI_assert(is_power_of_2_i(int(alignment)));
void *ptr = malloc(size + alignment + sizeof(MemHead));
void *used_ptr = reinterpret_cast<void *>(
uintptr_t(POINTER_OFFSET(ptr, alignment + sizeof(MemHead))) & ~(uintptr_t(alignment) - 1));
int offset = int(intptr_t(used_ptr) - intptr_t(ptr));
BLI_assert(offset >= int(sizeof(MemHead)));
(static_cast<MemHead *>(used_ptr) - 1)->offset = offset;
return used_ptr;
}
void deallocate(void *ptr)
{
MemHead *head = static_cast<MemHead *>(ptr) - 1;
int offset = -head->offset;
void *actual_pointer = POINTER_OFFSET(ptr, offset);
free(actual_pointer);
}
};
} // namespace blender