Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
LayoutSourceProviderRegistry.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <phosphorlayoutapi_export.h>
7
9
10#include <QDebug>
11#include <QList>
12#include <QMutex>
13#include <QString>
14
15#include <functional>
16#include <memory>
17#include <type_traits>
18#include <typeindex>
19#include <unordered_map>
20
21namespace PhosphorLayout {
22
65class PHOSPHORLAYOUTAPI_EXPORT FactoryContext
66{
67public:
93 template<typename T>
94 bool set(std::type_identity_t<T*> service)
95 {
96 // Compile-time guard for the void*-round-trip invariants
97 // documented above. T must be a class type (no plain pointers
98 // sneaking in via deduction), and its inheritance chain MUST be
99 // single (single-base) to keep static_cast<void*>(T*) ↔
100 // static_cast<T*>(void*) at a fixed offset. We can't statically
101 // detect virtual inheritance with pre-C++26 traits, but we can
102 // catch the most common silent-bug shape: a Concrete that
103 // multiply-inherits two non-related abstract bases would still
104 // round-trip safely under T == Concrete, but the documented
105 // pattern is to set<Interface>(...) — and that one does
106 // round-trip provided Interface itself sits at offset 0 in T.
107 // The runtime test in test_factory_context_typing covers the
108 // remaining cases.
109 static_assert(std::is_class_v<T>, "FactoryContext::set<T>: T must be a class type");
110 static_assert(!std::is_pointer_v<T>,
111 "FactoryContext::set<T>: pass the interface type, not a pointer type "
112 "(write set<IFoo>(p), not set<IFoo*>(p))");
113 const auto key = std::type_index(typeid(T));
114 const bool duplicate = m_services.find(key) != m_services.end();
115 Q_ASSERT_X(!duplicate, "FactoryContext::set",
116 "service key already registered; duplicate set<T>() is a programmer error");
117 if (duplicate) {
118 qWarning("FactoryContext::set: ignoring duplicate registration for type '%s' (first registration kept)",
119 key.name());
120 return false;
121 }
122 m_services[key] = static_cast<void*>(service);
123 return true;
124 }
125
130 template<typename T>
131 T* get() const
132 {
133 static_assert(std::is_class_v<T>, "FactoryContext::get<T>: T must be a class type");
134 static_assert(!std::is_pointer_v<T>,
135 "FactoryContext::get<T>: pass the interface type, not a pointer type "
136 "(write get<IFoo>(), not get<IFoo*>())");
137 const auto it = m_services.find(std::type_index(typeid(T)));
138 return it == m_services.end() ? nullptr : static_cast<T*>(it->second);
139 }
140
141private:
142 std::unordered_map<std::type_index, void*> m_services;
143};
144
152struct PHOSPHORLAYOUTAPI_EXPORT PendingLayoutSourceProvider
153{
154 QString name;
155 int priority = 100;
156 std::function<std::unique_ptr<ILayoutSourceFactory>(const FactoryContext&)> builder;
157};
158
196PHOSPHORLAYOUTAPI_EXPORT QList<PendingLayoutSourceProvider>& pendingLayoutSourceProviders();
197
200PHOSPHORLAYOUTAPI_EXPORT QMutex& pendingLayoutSourceProvidersMutex();
201
229class PHOSPHORLAYOUTAPI_EXPORT LayoutSourceProviderRegistrar
230{
231public:
232 LayoutSourceProviderRegistrar(QString name, int priority,
233 std::function<std::unique_ptr<ILayoutSourceFactory>(const FactoryContext&)> builder);
234};
235
249template<typename Registry, typename Factory>
250inline std::unique_ptr<ILayoutSourceFactory> makeProviderFactory(const FactoryContext& ctx)
251{
252 auto* registry = ctx.get<Registry>();
253 if (!registry) {
254 return nullptr;
255 }
256 return std::make_unique<Factory>(registry);
257}
258
259} // namespace PhosphorLayout
Service registry passed to a layout-source-provider builder so it can pull whatever registries / depe...
Definition LayoutSourceProviderRegistry.h:66
bool set(std::type_identity_t< T * > service)
Register a service of type T.
Definition LayoutSourceProviderRegistry.h:94
T * get() const
Look up a previously-registered service.
Definition LayoutSourceProviderRegistry.h:131
Static-init self-registration helper for provider libraries.
Definition LayoutSourceProviderRegistry.h:230
LayoutSourceProviderRegistrar(QString name, int priority, std::function< std::unique_ptr< ILayoutSourceFactory >(const FactoryContext &)> builder)
Definition AlgorithmMetadata.h:10
std::unique_ptr< ILayoutSourceFactory > makeProviderFactory(const FactoryContext &ctx)
Standard provider builder: pull Registry from ctx, return a new Factory bound to it,...
Definition LayoutSourceProviderRegistry.h:250
PHOSPHORLAYOUTAPI_EXPORT QMutex & pendingLayoutSourceProvidersMutex()
Mutex protecting pendingLayoutSourceProviders().
PHOSPHORLAYOUTAPI_EXPORT QList< PendingLayoutSourceProvider > & pendingLayoutSourceProviders()
Process-global list of pending provider registrations.
One pending layout-source-provider registration.
Definition LayoutSourceProviderRegistry.h:153
std::function< std::unique_ptr< ILayoutSourceFactory >(const FactoryContext &)> builder
Definition LayoutSourceProviderRegistry.h:156
QString name
Definition LayoutSourceProviderRegistry.h:154