From b5c2c3aba886f521a0cade5b8450683c20843d3a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 1 Apr 2021 15:55:08 +0200 Subject: BLI: rename resource collector to resource scope Differential Revision: https://developer.blender.org/D10857 --- source/blender/blenlib/BLI_resource_collector.hh | 158 --------------------- source/blender/blenlib/BLI_resource_scope.hh | 170 +++++++++++++++++++++++ source/blender/blenlib/CMakeLists.txt | 2 +- 3 files changed, 171 insertions(+), 159 deletions(-) delete mode 100644 source/blender/blenlib/BLI_resource_collector.hh create mode 100644 source/blender/blenlib/BLI_resource_scope.hh (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_resource_collector.hh b/source/blender/blenlib/BLI_resource_collector.hh deleted file mode 100644 index 70804ceb1f1..00000000000 --- a/source/blender/blenlib/BLI_resource_collector.hh +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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. - */ - -#pragma once - -/** \file - * \ingroup bli - * - * A ResourceCollector holds an arbitrary set of resources, that will be destructed and/or freed - * when the ResourceCollector is destructed. This is useful when some object has to take ownership - * of other objects, but it does not know the type of those other objects. - * - * Resources owned by the ResourceCollector will be freed in reverse order. That allows resources - * that are added later to depend on resources that have been added before. - */ - -#include "BLI_linear_allocator.hh" -#include "BLI_utility_mixins.hh" -#include "BLI_vector.hh" - -namespace blender { - -class ResourceCollector : NonCopyable, NonMovable { - private: - struct ResourceData { - void *data; - void (*free)(void *data); - const char *debug_name; - }; - - LinearAllocator<> m_allocator; - Vector m_resources; - - public: - ResourceCollector() = default; - - ~ResourceCollector() - { - /* Free in reversed order. */ - for (int64_t i = m_resources.size(); i--;) { - ResourceData &data = m_resources[i]; - data.free(data.data); - } - } - - /** - * Pass ownership of the resource to the ResourceCollector. It will be destructed and freed when - * the collector is destructed. - */ - template void add(std::unique_ptr resource, const char *name) - { - BLI_assert(resource.get() != nullptr); - this->add( - resource.release(), - [](void *data) { - T *typed_data = reinterpret_cast(data); - delete typed_data; - }, - name); - } - - /** - * Pass ownership of the resource to the ResourceCollector. It will be destructed when the - * collector is destructed. - */ - template void add(destruct_ptr resource, const char *name) - { - /* There is no need to keep track of such types. */ - if (std::is_trivially_destructible_v) { - resource.release(); - return; - } - - BLI_assert(resource.get() != nullptr); - this->add( - resource.release(), - [](void *data) { - T *typed_data = reinterpret_cast(data); - typed_data->~T(); - }, - name); - } - - /** - * Pass ownership of some resource to the ResourceCollector. The given free function will be - * called when the collector is destructed. - */ - void add(void *userdata, void (*free)(void *), const char *name) - { - ResourceData data; - data.debug_name = name; - data.data = userdata; - data.free = free; - m_resources.append(data); - } - - /** - * Construct an object with the same value in the ResourceCollector and return a reference to the - * new value. - */ - template T &add_value(T &&value, const char *name) - { - return this->construct(name, std::forward(value)); - } - - /** - * 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 m_allocator; - } - - /** - * Utility method to construct an instance of type T that will be owned by the ResourceCollector. - */ - template T &construct(const char *name, Args &&... args) - { - destruct_ptr value_ptr = m_allocator.construct(std::forward(args)...); - T &value_ref = *value_ptr; - this->add(std::move(value_ptr), name); - return value_ref; - } - - /** - * Print the names of all the resources that are owned by this ResourceCollector. This can be - * useful for debugging. - */ - void print(StringRef name) const - { - if (m_resources.size() == 0) { - std::cout << "\"" << name << "\" has no resources.\n"; - return; - } - else { - std::cout << "Resources for \"" << name << "\":\n"; - for (const ResourceData &data : m_resources) { - std::cout << " " << data.data << ": " << data.debug_name << '\n'; - } - } - } -}; - -} // namespace blender diff --git a/source/blender/blenlib/BLI_resource_scope.hh b/source/blender/blenlib/BLI_resource_scope.hh new file mode 100644 index 00000000000..f606dc0c0a1 --- /dev/null +++ b/source/blender/blenlib/BLI_resource_scope.hh @@ -0,0 +1,170 @@ +/* + * 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. + */ + +#pragma once + +/** \file + * \ingroup bli + * + * A `ResourceScope` takes ownership of arbitrary data/resources. Those resources will be + * destructed and/or freed when the `ResourceScope` is destructed. Destruction happens in reverse + * order. That allows resources do depend on other resources that have been added before. + * + * A `ResourceScope` can also be thought of as a dynamic/runtime version of normal scopes in C++ + * that are surrounded by braces. + * + * The main purpose of a `ResourceScope` is to allow functions to inject data into the scope of the + * caller. Traditionally, that can only be done by returning a value that owns everything it needs. + * This is fine until one has to deal with optional ownership. There are many ways to have a type + * optionally own something else, all of which are fairly annoying. A `ResourceScope` can be used + * to avoid having to deal with optional ownership. If some value would be owned, it can just be + * added to the resource scope, otherwise not. + * + * When a function takes a `ResourceScope` as parameter, it usually means that its return value + * will live at least as long as the passed in resources scope. However, it might also live longer. + * That can happen when the function returns a reference to statically allocated data or + * dynamically allocated data depending on some condition. + */ + +#include "BLI_linear_allocator.hh" +#include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" + +namespace blender { + +class ResourceScope : NonCopyable, NonMovable { + private: + struct ResourceData { + void *data; + void (*free)(void *data); + const char *debug_name; + }; + + LinearAllocator<> m_allocator; + Vector m_resources; + + public: + ResourceScope() = default; + + ~ResourceScope() + { + /* Free in reversed order. */ + for (int64_t i = m_resources.size(); i--;) { + ResourceData &data = m_resources[i]; + data.free(data.data); + } + } + + /** + * Pass ownership of the resource to the ResourceScope. It will be destructed and freed when + * the collector is destructed. + */ + template void add(std::unique_ptr resource, const char *name) + { + BLI_assert(resource.get() != nullptr); + this->add( + resource.release(), + [](void *data) { + T *typed_data = reinterpret_cast(data); + delete typed_data; + }, + name); + } + + /** + * Pass ownership of the resource to the ResourceScope. It will be destructed when the + * collector is destructed. + */ + template void add(destruct_ptr resource, const char *name) + { + /* There is no need to keep track of such types. */ + if (std::is_trivially_destructible_v) { + resource.release(); + return; + } + + BLI_assert(resource.get() != nullptr); + this->add( + resource.release(), + [](void *data) { + T *typed_data = reinterpret_cast(data); + typed_data->~T(); + }, + name); + } + + /** + * 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 *), const char *name) + { + ResourceData data; + data.debug_name = name; + data.data = userdata; + data.free = free; + m_resources.append(data); + } + + /** + * Construct an object with the same value in the ResourceScope and return a reference to the + * new value. + */ + template T &add_value(T &&value, const char *name) + { + return this->construct(name, std::forward(value)); + } + + /** + * 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 m_allocator; + } + + /** + * Utility method to construct an instance of type T that will be owned by the ResourceScope. + */ + template T &construct(const char *name, Args &&... args) + { + destruct_ptr value_ptr = m_allocator.construct(std::forward(args)...); + T &value_ref = *value_ptr; + this->add(std::move(value_ptr), name); + return value_ref; + } + + /** + * Print the names of all the resources that are owned by this ResourceScope. This can be + * useful for debugging. + */ + void print(StringRef name) const + { + if (m_resources.size() == 0) { + std::cout << "\"" << name << "\" has no resources.\n"; + return; + } + else { + std::cout << "Resources for \"" << name << "\":\n"; + for (const ResourceData &data : m_resources) { + std::cout << " " << data.data << ": " << data.debug_name << '\n'; + } + } + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index d7a27cc4531..e66049c9bd6 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -258,7 +258,7 @@ set(SRC BLI_rand.h BLI_rand.hh BLI_rect.h - BLI_resource_collector.hh + BLI_resource_scope.hh BLI_scanfill.h BLI_session_uuid.h BLI_set.hh -- cgit v1.2.3