Cleanup: move resource scope method definitions out of class

This commit is contained in:
Jacques Lucke 2021-10-03 14:23:26 +02:00
parent a8d6a86981
commit e1e75bd62c
3 changed files with 136 additions and 96 deletions

View File

@ -56,106 +56,113 @@ class ResourceScope : NonCopyable, NonMovable {
Vector<ResourceData> resources_;
public:
ResourceScope() = default;
ResourceScope();
~ResourceScope();
~ResourceScope()
{
/* Free in reversed order. */
for (int64_t i = resources_.size(); i--;) {
ResourceData &data = resources_[i];
data.free(data.data);
}
}
template<typename T> T *add(std::unique_ptr<T> resource);
template<typename T> T *add(destruct_ptr<T> resource);
void add(void *userdata, void (*free)(void *));
/**
* Pass ownership of the resource to the ResourceScope. It will be destructed and freed when
* the collector is destructed.
*/
template<typename T> T *add(std::unique_ptr<T> resource)
{
T *ptr = resource.release();
if (ptr == nullptr) {
return nullptr;
}
this->add(ptr, [](void *data) {
T *typed_data = reinterpret_cast<T *>(data);
delete typed_data;
});
return ptr;
}
template<typename T> T &add_value(T &&value);
template<typename Func> void add_destruct_call(Func func);
/**
* Pass ownership of the resource to the ResourceScope. It will be destructed when the
* collector is destructed.
*/
template<typename T> T *add(destruct_ptr<T> resource)
{
T *ptr = resource.release();
if (ptr == nullptr) {
return nullptr;
}
/* There is no need to keep track of such types. */
if (std::is_trivially_destructible_v<T>) {
return ptr;
}
template<typename T, typename... Args> T &construct(Args &&...args);
this->add(ptr, [](void *data) {
T *typed_data = reinterpret_cast<T *>(data);
typed_data->~T();
});
return ptr;
}
/**
* Pass ownership of some resource to the ResourceScope. The given free function will be
* called when the collector is destructed.
*/
void add(void *userdata, void (*free)(void *))
{
ResourceData data;
data.data = userdata;
data.free = free;
resources_.append(data);
}
/**
* Construct an object with the same value in the ResourceScope and return a reference to the
* new value.
*/
template<typename T> T &add_value(T &&value)
{
return this->construct<T>(std::forward<T>(value));
}
/**
* The passed in function will be called when the scope is destructed.
*/
template<typename Func> void add_destruct_call(Func func)
{
void *buffer = allocator_.allocate(sizeof(Func), alignof(Func));
new (buffer) Func(std::move(func));
this->add(buffer, [](void *data) { (*(Func *)data)(); });
}
/**
* Returns a reference to a linear allocator that is owned by the ResourcesCollector. Memory
* allocated through this allocator will be freed when the collector is destructed.
*/
LinearAllocator<> &linear_allocator()
{
return allocator_;
}
/**
* Utility method to construct an instance of type T that will be owned by the ResourceScope.
*/
template<typename T, typename... Args> T &construct(Args &&...args)
{
destruct_ptr<T> value_ptr = allocator_.construct<T>(std::forward<Args>(args)...);
T &value_ref = *value_ptr;
this->add(std::move(value_ptr));
return value_ref;
}
LinearAllocator<> &linear_allocator();
};
/* --------------------------------------------------------------------
* #ResourceScope inline methods.
*/
/**
* Pass ownership of the resource to the ResourceScope. It will be destructed and freed when
* the collector is destructed.
*/
template<typename T> inline T *ResourceScope::add(std::unique_ptr<T> resource)
{
T *ptr = resource.release();
if (ptr == nullptr) {
return nullptr;
}
this->add(ptr, [](void *data) {
T *typed_data = reinterpret_cast<T *>(data);
delete typed_data;
});
return ptr;
}
/**
* Pass ownership of the resource to the ResourceScope. It will be destructed when the
* collector is destructed.
*/
template<typename T> inline T *ResourceScope::add(destruct_ptr<T> resource)
{
T *ptr = resource.release();
if (ptr == nullptr) {
return nullptr;
}
/* There is no need to keep track of such types. */
if constexpr (std::is_trivially_destructible_v<T>) {
return ptr;
}
this->add(ptr, [](void *data) {
T *typed_data = reinterpret_cast<T *>(data);
typed_data->~T();
});
return ptr;
}
/**
* Pass ownership of some resource to the ResourceScope. The given free function will be
* called when the collector is destructed.
*/
inline void ResourceScope::add(void *userdata, void (*free)(void *))
{
ResourceData data;
data.data = userdata;
data.free = free;
resources_.append(data);
}
/**
* Construct an object with the same value in the ResourceScope and return a reference to the
* new value.
*/
template<typename T> inline T &ResourceScope::add_value(T &&value)
{
return this->construct<T>(std::forward<T>(value));
}
/**
* The passed in function will be called when the scope is destructed.
*/
template<typename Func> inline void ResourceScope::add_destruct_call(Func func)
{
void *buffer = allocator_.allocate(sizeof(Func), alignof(Func));
new (buffer) Func(std::move(func));
this->add(buffer, [](void *data) { (*(Func *)data)(); });
}
/**
* Utility method to construct an instance of type T that will be owned by the ResourceScope.
*/
template<typename T, typename... Args> inline T &ResourceScope::construct(Args &&...args)
{
destruct_ptr<T> value_ptr = allocator_.construct<T>(std::forward<Args>(args)...);
T &value_ref = *value_ptr;
this->add(std::move(value_ptr));
return value_ref;
}
/**
* Returns a reference to a linear allocator that is owned by the ResourcesCollector. Memory
* allocated through this allocator will be freed when the collector is destructed.
*/
inline LinearAllocator<> &ResourceScope::linear_allocator()
{
return allocator_;
}
} // namespace blender

View File

@ -124,6 +124,7 @@ set(SRC
intern/quadric.c
intern/rand.cc
intern/rct.c
intern/resource_scope.cc
intern/scanfill.c
intern/scanfill_utils.c
intern/session_uuid.c

View File

@ -0,0 +1,32 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "BLI_resource_scope.hh"
namespace blender {
ResourceScope::ResourceScope() = default;
ResourceScope::~ResourceScope()
{
/* Free in reversed order. */
for (int64_t i = resources_.size(); i--;) {
ResourceData &data = resources_[i];
data.free(data.data);
}
}
} // namespace blender