Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
# SPDX-FileCopyrightText: 2006 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
PUBLIC .
..
)
set(INC_SYS
)
set(SRC
intern/MEM_CacheLimiterC-Api.cpp
intern/MEM_RefCountedC-Api.cpp
intern/MEM_alloc_string_storage.cc
MEM_Allocator.h
MEM_CacheLimiter.h
MEM_CacheLimiterC-Api.h
MEM_RefCounted.h
MEM_RefCountedC-Api.h
MEM_alloc_string_storage.hh
)
set(LIB
PRIVATE bf::blenlib
PRIVATE bf::intern::guardedalloc
)
blender_add_lib(bf_intern_memutil "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
add_library(bf::intern::memutil ALIAS bf_intern_memutil)

View File

@@ -0,0 +1,78 @@
/* SPDX-FileCopyrightText: 2006-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*/
#ifndef __MEM_ALLOCATOR_H__
#define __MEM_ALLOCATOR_H__
#include "guardedalloc/MEM_guardedalloc.h"
#include <cstddef>
template<typename _Tp> struct MEM_Allocator {
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Tp *;
using const_pointer = const _Tp *;
using reference = _Tp &;
using const_reference = const _Tp &;
using value_type = _Tp;
template<typename _Tp1> struct rebind {
using other = MEM_Allocator<_Tp1>;
};
MEM_Allocator() noexcept = default;
MEM_Allocator(const MEM_Allocator & /*other*/) noexcept = default;
template<typename _Tp1> MEM_Allocator(const MEM_Allocator<_Tp1> /*other*/) noexcept {}
~MEM_Allocator() noexcept = default;
pointer address(reference __x) const
{
return &__x;
}
const_pointer address(const_reference __x) const
{
return &__x;
}
/* NOTE: `__n` is permitted to be 0.
* The C++ standard says nothing about what the return value is when `__n == 0`. */
_Tp *allocate(size_type __n, const void * /*unused*/ = nullptr)
{
_Tp *__ret = NULL;
if (__n) {
__ret = static_cast<_Tp *>(MEM_new_uninitialized(__n * sizeof(_Tp), "STL MEM_Allocator"));
}
return __ret;
}
// __p is not permitted to be a null pointer.
void deallocate(pointer __p, size_type /*unused*/)
{
MEM_delete_void(static_cast<void *>(__p));
}
size_type max_size() const noexcept
{
return size_t(-1) / sizeof(_Tp);
}
void construct(pointer __p, const _Tp &__val)
{
new (__p) _Tp(__val);
}
void destroy(pointer __p)
{
__p->~_Tp();
}
};
#endif // __MEM_ALLOCATOR_H__

View File

@@ -0,0 +1,315 @@
/* SPDX-FileCopyrightText: 2006-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*/
#ifndef __MEM_CACHELIMITER_H__
#define __MEM_CACHELIMITER_H__
/**
* \section MEM_CacheLimiter
* This class defines a generic memory cache management system
* to limit memory usage to a fixed global maximum.
*
* \note Please use the C-API in MEM_CacheLimiterC-Api.h for code written in C.
*
* Usage example:
*
* \code{.cpp}
* class BigFatImage {
* public:
* ~BigFatImage() { tell_everyone_we_are_gone(this); }
* };
*
* void doit()
* {
* MEM_Cache<BigFatImage> BigFatImages;
*
* MEM_Cache_Handle<BigFatImage>* h = BigFatImages.insert(new BigFatImage);
*
* BigFatImages.enforce_limits();
* h->ref();
*
* // work with image...
*
* h->unref();
*
* // leave image in cache.
* \endcode
*/
#include "MEM_Allocator.h"
#include <vector>
template<class T> class MEM_CacheLimiter;
#ifndef __MEM_CACHELIMITERC_API_H__
extern "C" {
void MEM_CacheLimiter_set_maximum(size_t m);
size_t MEM_CacheLimiter_get_maximum();
void MEM_CacheLimiter_set_disabled(bool disabled);
bool MEM_CacheLimiter_is_disabled(void);
};
#endif
template<class T> class MEM_CacheLimiterHandle {
public:
explicit MEM_CacheLimiterHandle(T *data_, MEM_CacheLimiter<T> *parent_)
: data(data_), parent(parent_)
{
}
void ref()
{
refcount++;
}
void unref()
{
refcount--;
}
T *get()
{
return data;
}
const T *get() const
{
return data;
}
int get_refcount() const
{
return refcount;
}
bool can_destroy() const
{
return !data || !refcount;
}
bool destroy_if_possible()
{
if (can_destroy()) {
delete data;
data = NULL;
unmanage();
return true;
}
return false;
}
void unmanage()
{
parent->unmanage(this);
}
void touch()
{
parent->touch(this);
}
private:
friend class MEM_CacheLimiter<T>;
T *data;
int refcount = 0;
int pos;
MEM_CacheLimiter<T> *parent;
};
template<class T> class MEM_CacheLimiter {
public:
using MEM_CacheLimiter_DataSize_Func = size_t (*)(void *);
using MEM_CacheLimiter_ItemPriority_Func = int (*)(void *, int);
using MEM_CacheLimiter_ItemDestroyable_Func = bool (*)(void *);
MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func data_size_func) : data_size_func(data_size_func)
{
}
~MEM_CacheLimiter()
{
int i;
for (i = 0; i < queue.size(); i++) {
delete queue[i];
}
}
MEM_CacheLimiterHandle<T> *insert(T *elem)
{
queue.push_back(new MEM_CacheLimiterHandle<T>(elem, this));
queue.back()->pos = queue.size() - 1;
return queue.back();
}
void unmanage(MEM_CacheLimiterHandle<T> *handle)
{
int pos = handle->pos;
queue[pos] = queue.back();
queue[pos]->pos = pos;
queue.pop_back();
delete handle;
}
size_t get_memory_in_use()
{
size_t size = 0;
if (data_size_func) {
int i;
for (i = 0; i < queue.size(); i++) {
size += data_size_func(queue[i]->get()->get_data());
}
}
else {
size = MEM_get_memory_in_use();
}
return size;
}
void enforce_limits()
{
size_t max = MEM_CacheLimiter_get_maximum();
bool is_disabled = MEM_CacheLimiter_is_disabled();
size_t mem_in_use, cur_size;
if (is_disabled) {
return;
}
if (max == 0) {
return;
}
mem_in_use = get_memory_in_use();
if (mem_in_use <= max) {
return;
}
while (!queue.empty() && mem_in_use > max) {
MEM_CacheElementPtr elem = get_least_priority_destroyable_element();
if (!elem) {
break;
}
if (data_size_func) {
cur_size = data_size_func(elem->get()->get_data());
}
else {
cur_size = mem_in_use;
}
if (elem->destroy_if_possible()) {
if (data_size_func) {
mem_in_use -= cur_size;
}
else {
mem_in_use -= cur_size - MEM_get_memory_in_use();
}
}
}
}
void touch(MEM_CacheLimiterHandle<T> *handle)
{
/* If we're using custom priority callback re-arranging the queue
* doesn't make much sense because we'll iterate it all to get
* least priority element anyway.
*/
if (item_priority_func == nullptr) {
queue[handle->pos] = queue.back();
queue[handle->pos]->pos = handle->pos;
queue.pop_back();
queue.push_back(handle);
handle->pos = queue.size() - 1;
}
}
void set_item_priority_func(MEM_CacheLimiter_ItemPriority_Func item_priority_func)
{
this->item_priority_func = item_priority_func;
}
void set_item_destroyable_func(MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func)
{
this->item_destroyable_func = item_destroyable_func;
}
private:
using MEM_CacheElementPtr = MEM_CacheLimiterHandle<T> *;
using MEM_CacheQueue = std::vector<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr>>;
using iterator = typename MEM_CacheQueue::iterator;
/* Check whether element can be destroyed when enforcing cache limits */
bool can_destroy_element(MEM_CacheElementPtr &elem)
{
if (!elem->can_destroy()) {
/* Element is referenced */
return false;
}
if (item_destroyable_func) {
if (!item_destroyable_func(elem->get()->get_data())) {
return false;
}
}
return true;
}
MEM_CacheElementPtr get_least_priority_destroyable_element()
{
if (queue.empty()) {
return NULL;
}
MEM_CacheElementPtr best_match_elem = NULL;
if (!item_priority_func) {
for (iterator it = queue.begin(); it != queue.end(); it++) {
MEM_CacheElementPtr elem = *it;
if (!can_destroy_element(elem)) {
continue;
}
best_match_elem = elem;
break;
}
}
else {
int best_match_priority = 0;
int i;
for (i = 0; i < queue.size(); i++) {
MEM_CacheElementPtr elem = queue[i];
if (!can_destroy_element(elem)) {
continue;
}
/* By default 0 means highest priority element. */
/* Casting a size type to int is questionable,
* but unlikely to cause problems. */
int priority = -((int)(queue.size()) - i - 1);
priority = item_priority_func(elem->get()->get_data(), priority);
if (priority < best_match_priority || best_match_elem == NULL) {
best_match_priority = priority;
best_match_elem = elem;
}
}
}
return best_match_elem;
}
MEM_CacheQueue queue;
MEM_CacheLimiter_DataSize_Func data_size_func;
MEM_CacheLimiter_ItemPriority_Func item_priority_func;
MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func;
};
#endif // __MEM_CACHELIMITER_H__

View File

@@ -0,0 +1,144 @@
/* SPDX-FileCopyrightText: 2006-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*/
#ifndef __MEM_CACHELIMITERC_API_H__
#define __MEM_CACHELIMITERC_API_H__
#include <cstddef>
#ifdef __cplusplus
extern "C" {
#endif
struct MEM_CacheLimiter_s;
struct MEM_CacheLimiterHandle_s;
using MEM_CacheLimiterC = struct MEM_CacheLimiter_s;
using MEM_CacheLimiterHandleC = struct MEM_CacheLimiterHandle_s;
/* function used to remove data from memory */
using MEM_CacheLimiter_Destruct_Func = void (*)(void *);
/* function used to measure stored data element size */
using MEM_CacheLimiter_DataSize_Func = size_t (*)(void *);
/* function used to measure priority of item when freeing memory */
using MEM_CacheLimiter_ItemPriority_Func = int (*)(void *, int);
/* function to check whether item could be destroyed */
using MEM_CacheLimiter_ItemDestroyable_Func = bool (*)(void *);
#ifndef __MEM_CACHELIMITER_H__
void MEM_CacheLimiter_set_maximum(size_t m);
size_t MEM_CacheLimiter_get_maximum(void);
void MEM_CacheLimiter_set_disabled(bool disabled);
bool MEM_CacheLimiter_is_disabled(void);
#endif /* __MEM_CACHELIMITER_H__ */
/**
* Create new MEM_CacheLimiter object
* managed objects are destructed with the data_destructor
*
* \param data_destructor: TODO.
* \return A new #MEM_CacheLimter object.
*/
MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_destructor,
MEM_CacheLimiter_DataSize_Func data_size);
/**
* Delete MEM_CacheLimiter
*
* Frees the memory of the CacheLimiter but does not touch managed objects!
*
* \param This: "This" pointer.
*/
void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This);
/**
* Manage object
*
* \param This: "This" pointer, data object to manage.
* \return The handle to reference/unreference & touch the managed object.
*/
MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *data);
/**
* Free objects until memory constraints are satisfied
*
* \param This: "This" pointer.
*/
void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This);
/**
* Unmanage object previously inserted object.
* Does _not_ delete managed object!
*
* \param handle: of object.
*/
void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle);
/**
* Raise priority of object (put it at the tail of the deletion chain)
*
* \param handle: of object.
*/
void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle);
/**
* Increment reference counter. Objects with reference counter != 0 are _not_
* deleted.
*
* \param handle: of object.
*/
void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle);
/**
* Decrement reference counter. Objects with reference counter != 0 are _not_
* deleted.
*
* \param handle: of object.
*/
void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle);
/**
* Get reference counter.
*
* \param handle: of object.
*/
int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle);
/**
* Get pointer to managed object
*
* \param handle: of object.
*/
void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle);
void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This,
MEM_CacheLimiter_ItemPriority_Func item_priority_func);
void MEM_CacheLimiter_ItemDestroyable_Func_set(
MEM_CacheLimiterC *This, MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func);
size_t MEM_CacheLimiter_get_memory_in_use(MEM_CacheLimiterC *This);
#ifdef __cplusplus
}
#endif
#endif // __MEM_CACHELIMITERC_API_H__

View File

@@ -0,0 +1,82 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*
* Declaration of MEM_RefCounted class.
*/
#ifndef __MEM_REFCOUNTED_H__
#define __MEM_REFCOUNTED_H__
/**
* An object with reference counting.
* Base class for objects with reference counting.
* When a shared object is ceated, it has reference count == 1.
* If the reference count of a shared object reaches zero, the object self-destructs.
* The default destructor of this object has been made protected on purpose.
* This disables the creation of shared objects on the stack.
*
* \author Maarten Gribnau
* \date March 31, 2001
*/
class MEM_RefCounted {
public:
/**
* Constructs a shared object.
*/
MEM_RefCounted() = default;
/**
* Returns the reference count of this object.
* \return the reference count.
*/
inline virtual int getRef() const;
/**
* Increases the reference count of this object.
* \return the new reference count.
*/
inline virtual int incRef();
/**
* Decreases the reference count of this object.
* If the reference count reaches zero, the object self-destructs.
* \return the new reference count.
*/
inline virtual int decRef();
protected:
/**
* Destructs a shared object.
* The destructor is protected to force the use of incRef and decRef.
*/
virtual ~MEM_RefCounted() = default;
/** The reference count. */
int m_refCount = 1;
};
inline int MEM_RefCounted::getRef() const
{
return m_refCount;
}
inline int MEM_RefCounted::incRef()
{
return ++m_refCount;
}
inline int MEM_RefCounted::decRef()
{
m_refCount--;
if (m_refCount == 0) {
delete this;
return 0;
}
return m_refCount;
}
#endif // __MEM_REFCOUNTED_H__

View File

@@ -0,0 +1,49 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*
* Interface for C access to functionality relating to shared objects in the foundation library.
*/
#ifndef __MEM_REFCOUNTEDC_API_H__
#define __MEM_REFCOUNTEDC_API_H__
/** A pointer to a private object. */
using MEM_TObjectPtr = struct MEM_TOpaqueObject *;
/** A pointer to a shared object. */
using MEM_TRefCountedObjectPtr = MEM_TObjectPtr;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Returns the reference count of this object.
* \param shared: The object to query.
* \return The current reference count.
*/
extern int MEM_RefCountedGetRef(MEM_TRefCountedObjectPtr shared);
/**
* Increases the reference count of this object.
* \param shared: The object to query.
* \return The new reference count.
*/
extern int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared);
/**
* Decreases the reference count of this object.
* If the reference count reaches zero, the object self-destructs.
* \param shared: The object to query.
* \return The new reference count.
*/
extern int MEM_RefCountedDecRef(MEM_TRefCountedObjectPtr shared);
#ifdef __cplusplus
}
#endif
#endif // __MEM_REFCOUNTEDC_API_H__

View File

@@ -0,0 +1,118 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup intern_memutil
*
* Implement a static storage for complex, non-static allocation strings passed MEM_guardedalloc
* functions.
*/
#include <any>
#include <cassert>
#include <string>
#include <unordered_map>
namespace intern::memutil {
/**
* A 'static' storage of allocation strings, with a simple API to set and retrieve them.
*
* This is a templated wrapper around a std::unordered_map, to allow custom key types.
*/
template<typename keyT, template<typename> typename hashT> class AllocStringStorage {
std::unordered_map<keyT, std::string, hashT<keyT>> storage_;
public:
/**
* Check whether the given key exists in the storage.
*
* \return `true` if the \a key is found in storage, false otherwise.
*/
bool contains(const keyT &key)
{
return storage_.count(key) != 0;
}
/**
* Return the alloc string for the given key in the storage.
*
* \return A pointer to the stored string if \a key is found, `nullptr` otherwise.
*/
const char *find(const keyT &key)
{
if (storage_.count(key) != 0) {
return storage_[key].c_str();
}
return nullptr;
}
/**
* Insert the given alloc string in the storage, at the given key, and return a pointer
* to the stored string.
*
* \param alloc_string: The alloc string to store at \a key.
* \return A pointer to the inserted stored string.
*/
const char *insert(const keyT &key, std::string alloc_string)
{
#ifndef NDEBUG
assert(storage_.count(key) == 0);
#endif
return (storage_[key] = std::move(alloc_string)).c_str();
}
};
namespace internal {
/**
* The main container for all #AllocStringStorage.
*/
class AllocStringStorageContainer {
std::unordered_map<std::string, std::any> storage_;
public:
/**
* Create if necessary, and return the #AllocStringStorage for the given \a storage_identifier.
*
* The template arguments allow to define the type of key used for the mapping to allocation
* strings.
*/
template<typename keyT, template<typename> typename hashT>
std::any &ensure_storage(const std::string &storage_identifier)
{
if (!storage_.contains(storage_identifier)) {
AllocStringStorage<keyT, hashT> storage_for_identifier;
return (storage_[storage_identifier] = std::make_any<AllocStringStorage<keyT, hashT>>(
std::move(storage_for_identifier)));
}
return storage_[storage_identifier];
}
};
/**
* Ensure that the static AllocStringStorageContainer is defined and created, and return a
* reference to it.
*/
AllocStringStorageContainer &ensure_storage_container();
} // namespace internal
/**
* Return a reference to the AllocStringStorage static data matching the given \a
* storage_identifier, creating it if needed.
*
* \note The storage is `thread_local` data, so access to it is thread-safe as long as it is not
* shared between threads by the user code.
*/
template<typename keyT, template<typename> typename hashT>
AllocStringStorage<keyT, hashT> &alloc_string_storage_get(const std::string &storage_identifier)
{
internal::AllocStringStorageContainer &storage_container = internal::ensure_storage_container();
std::any &storage = storage_container.ensure_storage<keyT, hashT>(storage_identifier);
return std::any_cast<AllocStringStorage<keyT, hashT> &>(storage);
}
} // namespace intern::memutil

View File

@@ -0,0 +1,218 @@
/* SPDX-FileCopyrightText: 2006-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*/
#include <cstddef>
#include <list>
#include "MEM_CacheLimiter.h"
#include "MEM_CacheLimiterC-Api.h"
static bool is_disabled = false;
static size_t &get_max()
{
static size_t m = 32 * 1024 * 1024;
return m;
}
void MEM_CacheLimiter_set_maximum(size_t m)
{
get_max() = m;
}
size_t MEM_CacheLimiter_get_maximum()
{
return get_max();
}
void MEM_CacheLimiter_set_disabled(bool disabled)
{
is_disabled = disabled;
}
bool MEM_CacheLimiter_is_disabled(void)
{
return is_disabled;
}
class MEM_CacheLimiterHandleCClass;
class MEM_CacheLimiterCClass;
using handle_t = MEM_CacheLimiterHandle<MEM_CacheLimiterHandleCClass>;
using cache_t = MEM_CacheLimiter<MEM_CacheLimiterHandleCClass>;
using list_t =
std::list<MEM_CacheLimiterHandleCClass *, MEM_Allocator<MEM_CacheLimiterHandleCClass *>>;
class MEM_CacheLimiterCClass {
public:
MEM_CacheLimiterCClass(MEM_CacheLimiter_Destruct_Func data_destructor_,
MEM_CacheLimiter_DataSize_Func data_size)
: data_destructor(data_destructor_), cache(data_size)
{
}
~MEM_CacheLimiterCClass();
handle_t *insert(void *data);
void destruct(void *data, list_t::iterator it);
cache_t *get_cache()
{
return &cache;
}
private:
MEM_CacheLimiter_Destruct_Func data_destructor;
MEM_CacheLimiter<MEM_CacheLimiterHandleCClass> cache;
list_t cclass_list;
};
class MEM_CacheLimiterHandleCClass {
public:
MEM_CacheLimiterHandleCClass(void *data_, MEM_CacheLimiterCClass *parent_)
: data(data_), parent(parent_)
{
}
~MEM_CacheLimiterHandleCClass();
void set_iter(list_t::iterator it_)
{
it = it_;
}
void set_data(void *data_)
{
data = data_;
}
void *get_data() const
{
return data;
}
private:
void *data;
MEM_CacheLimiterCClass *parent;
list_t::iterator it;
};
handle_t *MEM_CacheLimiterCClass::insert(void *data)
{
cclass_list.push_back(new MEM_CacheLimiterHandleCClass(data, this));
list_t::iterator it = cclass_list.end();
--it;
cclass_list.back()->set_iter(it);
return cache.insert(cclass_list.back());
}
void MEM_CacheLimiterCClass::destruct(void *data, list_t::iterator it)
{
data_destructor(data);
cclass_list.erase(it);
}
MEM_CacheLimiterHandleCClass::~MEM_CacheLimiterHandleCClass()
{
if (data) {
parent->destruct(data, it);
}
}
MEM_CacheLimiterCClass::~MEM_CacheLimiterCClass()
{
// should not happen, but don't leak memory in this case...
for (list_t::iterator it = cclass_list.begin(); it != cclass_list.end(); it++) {
(*it)->set_data(nullptr);
delete *it;
}
}
// ----------------------------------------------------------------------
static inline MEM_CacheLimiterCClass *cast(MEM_CacheLimiterC *l)
{
return (MEM_CacheLimiterCClass *)l;
}
static inline handle_t *cast(MEM_CacheLimiterHandleC *l)
{
return (handle_t *)l;
}
MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_destructor,
MEM_CacheLimiter_DataSize_Func data_size)
{
return (MEM_CacheLimiterC *)new MEM_CacheLimiterCClass(data_destructor, data_size);
}
void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This)
{
delete cast(This);
}
MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *data)
{
return (MEM_CacheLimiterHandleC *)cast(This)->insert(data);
}
void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This)
{
cast(This)->get_cache()->enforce_limits();
}
void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle)
{
cast(handle)->unmanage();
}
void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle)
{
cast(handle)->touch();
}
void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle)
{
cast(handle)->ref();
}
void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle)
{
cast(handle)->unref();
}
int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle)
{
return cast(handle)->get_refcount();
}
void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle)
{
return cast(handle)->get()->get_data();
}
void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This,
MEM_CacheLimiter_ItemPriority_Func item_priority_func)
{
cast(This)->get_cache()->set_item_priority_func(item_priority_func);
}
void MEM_CacheLimiter_ItemDestroyable_Func_set(
MEM_CacheLimiterC *This, MEM_CacheLimiter_ItemDestroyable_Func item_destroyable_func)
{
cast(This)->get_cache()->set_item_destroyable_func(item_destroyable_func);
}
size_t MEM_CacheLimiter_get_memory_in_use(MEM_CacheLimiterC *This)
{
return cast(This)->get_cache()->get_memory_in_use();
}

View File

@@ -0,0 +1,25 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*/
#include "MEM_RefCountedC-Api.h"
#include "MEM_RefCounted.h"
int MEM_RefCountedGetRef(MEM_TRefCountedObjectPtr shared)
{
return shared ? ((MEM_RefCounted *)shared)->getRef() : 0;
}
int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared)
{
return shared ? ((MEM_RefCounted *)shared)->incRef() : 0;
}
int MEM_RefCountedDecRef(MEM_TRefCountedObjectPtr shared)
{
return shared ? ((MEM_RefCounted *)shared)->decRef() : 0;
}

View File

@@ -0,0 +1,21 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_memutil
*/
#include "MEM_alloc_string_storage.hh"
#include "MEM_guardedalloc.h"
namespace intern::memutil::internal {
AllocStringStorageContainer &ensure_storage_container()
{
static thread_local AllocStringStorageContainer &storage =
MEM_construct_leak_detection_data<AllocStringStorageContainer>();
return storage;
}
} // namespace intern::memutil::internal