1
0
Fork 0

Codechange: ProviderManager class to support self-registration of providers.

This is based loosely on TimerManager.
pull/13152/head
Peter Nelson 2024-10-17 00:08:47 +01:00 committed by Peter Nelson
parent bccf5343f4
commit 7e8bcf44f7
2 changed files with 108 additions and 0 deletions

View File

@ -345,6 +345,7 @@ add_files(
picker_gui.h
progress.cpp
progress.h
provider_manager.h
querystring_gui.h
rail.cpp
rail.h

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/** @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 <typename TProviderType>
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<TProviderType *> &GetProviders()
{
static std::vector<TProviderType *> providers{};
return providers;
}
};
template <typename T>
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 <typename T>
class PriorityBaseProvider : public BaseProvider<T> {
public:
constexpr PriorityBaseProvider(std::string_view name, std::string_view description, int priority) : BaseProvider<T>(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 */