From 7e8bcf44f7ac45caba0dd1271f7fa6e71a59a138 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 17 Oct 2024 00:08:47 +0100 Subject: [PATCH] Codechange: ProviderManager class to support self-registration of providers. This is based loosely on TimerManager. --- src/CMakeLists.txt | 1 + src/provider_manager.h | 107 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/provider_manager.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f7cfdcb2b..add6ebbe4d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -345,6 +345,7 @@ add_files( picker_gui.h progress.cpp progress.h + provider_manager.h querystring_gui.h rail.cpp rail.h diff --git a/src/provider_manager.h b/src/provider_manager.h new file mode 100644 index 0000000000..44caa03963 --- /dev/null +++ b/src/provider_manager.h @@ -0,0 +1,107 @@ +/* + * This file is part of OpenTTD. + * OpenTTD 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, version 2. + * OpenTTD 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 OpenTTD. If not, see . + */ + +/** @file provider_manager.h Definition of the ProviderManager */ + +#ifndef PROVIDER_MANAGER_H +#define PROVIDER_MANAGER_H + +/** + * The ProviderManager manages a single Provider-type. + * + * It allows for automatic registration and unregistration of providers. + * + * @tparam T Service provider type. + */ +template +class ProviderManager { +public: + /* Avoid copying this object; it is a singleton object. */ + ProviderManager(ProviderManager const &) = delete; + + ProviderManager &operator=(ProviderManager const &) = delete; + + static void Register(TProviderType &instance) + { + /* Insert according to comparator. */ + auto &providers = GetProviders(); + auto it = std::ranges::lower_bound(providers, &instance, typename TProviderType::ProviderSorter()); + providers.insert(it, &instance); + } + + static void Unregister(TProviderType &instance) + { + auto &providers = GetProviders(); + providers.erase(std::find(std::begin(providers), std::end(providers), &instance)); + } + + /** + * Get the currently known sound loaders. + * @return The known sound loaders. + */ + static std::vector &GetProviders() + { + static std::vector providers{}; + return providers; + } +}; + +template +class BaseProvider { +public: + constexpr BaseProvider(std::string_view name, std::string_view description) : name(name), description(description) {} + virtual ~BaseProvider() {} + + inline std::string_view GetName() const { return this->name; } + inline std::string_view GetDescription() const { return this->description; } + + /** + * Sorter for BaseProvider. + * + * It will sort based on the name. If the name is the + * same, it will sort based on the pointer value. + */ + struct ProviderSorter { + bool operator()(const T *a, const T *b) const + { + if (a->GetName() == b->GetName()) return a < b; + return a->GetName() < b->GetName(); + } + }; + +protected: + const std::string_view name; + const std::string_view description; +}; + +template +class PriorityBaseProvider : public BaseProvider { +public: + constexpr PriorityBaseProvider(std::string_view name, std::string_view description, int priority) : BaseProvider(name, description), priority(priority) {} + virtual ~PriorityBaseProvider() {} + + inline int GetPriority() const { return this->priority; } + + /** + * Sorter for PriorityBaseProvider. + * + * It will sort based on the priority, smaller first. If the priority is the + * same, it will sort based on the pointer value. + */ + struct ProviderSorter { + bool operator()(const T *a, const T *b) const + { + if (a->GetPriority() == b->GetPriority()) return a < b; + return a->GetPriority() < b->GetPriority(); + } + }; + +protected: + const int priority; +}; + +#endif /* PROVIDER_MANAGER_H */