Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/BLI_resource_collector.hh')
-rw-r--r--source/blender/blenlib/BLI_resource_collector.hh148
1 files changed, 148 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_resource_collector.hh b/source/blender/blenlib/BLI_resource_collector.hh
new file mode 100644
index 00000000000..20180f3b2c9
--- /dev/null
+++ b/source/blender/blenlib/BLI_resource_collector.hh
@@ -0,0 +1,148 @@
+/*
+ * 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<ResourceData> 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<typename T> void add(std::unique_ptr<T> resource, const char *name)
+ {
+ BLI_assert(resource.get() != nullptr);
+ this->add(
+ resource.release(),
+ [](void *data) {
+ T *typed_data = reinterpret_cast<T *>(data);
+ delete typed_data;
+ },
+ name);
+ }
+
+ /**
+ * Pass ownership of the resource to the ResourceCollector. It will be destructed when the
+ * collector is destructed.
+ */
+ template<typename T> void add(destruct_ptr<T> resource, const char *name)
+ {
+ /* There is no need to keep track of such types. */
+ if (std::is_trivially_destructible_v<T>) {
+ resource.release();
+ return;
+ }
+
+ BLI_assert(resource.get() != nullptr);
+ this->add(
+ resource.release(),
+ [](void *data) {
+ T *typed_data = reinterpret_cast<T *>(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);
+ }
+
+ /**
+ * 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<typename T, typename... Args> T &construct(const char *name, Args &&... args)
+ {
+ T *value = m_allocator.construct<T>(std::forward<Args>(args)...);
+ this->add(destruct_ptr<T>(value), name);
+ return *value;
+ }
+
+ /**
+ * 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