ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
plugins.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_lang of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib::lang {
9
10//==================================================================================================
11/// This class usually is used as a base class for types that need to manage simple plug-ins.
12/// Within \alib itself, for example classes \alib{variables;Configuration} and
13/// \alib{expressions;Compiler} inherit from this class.
14///
15/// Plug-ins are organized with a prioritization. This means, that plug-ins which are inserted with
16/// a higher priority are 'asked' first, and those with a lower value become 'asked' only if higher
17/// prioritized plug-ins did not answer.<br>
18/// However, a derived class can deviate from this behavior. Using the typical \alib class design,
19/// all internal fields are \c protected, hence freely accessible by derived classes.
20///
21/// @tparam TPlugin The plug-in type that this class manages. This type is publicly exposed as
22/// #PluginType
23/// This type is publicly exposed as #PrioritiesType.
24//==================================================================================================
25template<typename TPlugin, typename TPriorities>
26class Plugin
27{
28 public:
29 /// This exposes the template parameter \p{TPlugin} to the outer world.
30 using PluginType= TPlugin;
31
32 /// This exposes the template parameter \p{pTPlugin} to the outer world.
33 using PrioritiesType= TPriorities;
34
35 protected:
36 /// The priority of this plug-in.
38
39 /// Constructor which is protected, as this is a bace class.
40 /// @param pPriority The priority that this plug-in uses.
42 : priority (pPriority) {}
43
44 public:
45 /// Returns the priority of this plug-in which is set during construction.
46 /// @return The priority of this plugin.
48
49}; //class Plugin
50
51//==================================================================================================
52/// This class usually is used as a base class for types that need to manage simple plug-ins.
53/// Within \alib itself, for example classes \alib{variables;Configuration} and
54/// \alib{expressions;Compiler} inherit from this class.
55///
56/// Plug-ins are organized with a prioritization. This means, that plug-ins which are inserted with
57/// a higher priority are 'asked' first, and those with a lower value become 'asked' only if higher
58/// prioritized plug-ins did not answer.<br>
59/// However, a derived class can deviate from this behavior. Using the typical \alib class design,
60/// all internal fields are \c protected, hence freely accessible by derived classes.
61///
62/// @tparam TPlugin The type of the plug-ins managed. This type is publicly exposed as
63/// #PluginType.
64/// @tparam TPriorities The enumeration type providing the default "plug-in slots" and priorities
65/// of the plug-ins managed. This type is publicly exposed as #PrioritiesType.
66//==================================================================================================
67template<typename TPlugin, typename TPriorities>
69{
70 // #############################################################################################
71 // public fields and types
72 // #############################################################################################
73 public:
74 /// This exposes the template parameter \p{pTPlugin} to the outer world.
75 using PluginType= TPlugin;
76
77 /// This exposes the template parameter \p{pTPlugin} to the outer world.
78 using PrioritiesType= TPriorities;
79
80 /// Type definition for elements of the list of plug-ins with their priority.
81 struct Slot
82 {
83 TPlugin* plugin; ///< The plug-in.
84 bool owned; ///< If \c true, this container is responsible for deleting
85 ///< the plug-in object.
86 };
87
88 /// The list that stores the plugins.
89 using PluginList= std::vector<Slot>;
90
91 // #############################################################################################
92 // internal fields
93 // #############################################################################################
94 protected:
95
96 /// The plug-ins we have attached in descending priority order.
98
99 // #############################################################################################
100 // Constructor/destructor
101 // #############################################################################################
102 public:
103 //==========================================================================================
104 /// Destructor. All plug-ins that were inserted with parameter \p{responsibility} set to
105 /// \alib{lang;Responsibility::Transfer} will be deleted.
106 //==========================================================================================
108 {
109 for( auto& slot : plugins )
110 if( slot.owned )
111 delete slot.plugin;
112 }
113
114
115
116 // #############################################################################################
117 // interface
118 // #############################################################################################
119 public:
120 //==========================================================================================
121 /// Adds the given plug-in to the list of plug-ins.
122 ///
123 /// @param plugin The plug-in to insert.
124 /// @param responsibility If \c Responsibility::Transfer, the given plugin will be deleted
125 /// with destruction of this object.
126 /// Defaults to \c Responsibility::KeepWithSender which denotes that
127 /// the life-cycle of the given external buffer is managed elsewhere.
128 //==========================================================================================
129 void InsertPlugin( TPlugin* plugin, lang::Responsibility responsibility
131 {
132 ALIB_ASSERT_ERROR( plugin != nullptr, "FSPLUGINS", "Nullptr provided for plugin." )
133
134 ALIB_STATIC_ASSERT( Plugin_type_not_virtual,
135 std::has_virtual_destructor<TPlugin>::value
136 || responsibility == lang::Responsibility::KeepWithSender,
137 "Can't take responsibility for plug-in destruction. TPlugin has no virtual destructor.")
138
139 // gcc needs this captured, clang warns.
140 // Its about the ALIB_CALLER inside ALIB_ASSERT_ERROR
142 plugins.insert( std::find_if( plugins.begin(), plugins.end(),
143 [plugin,this]( Slot& ppp)
144 {
145 ALIB_ASSERT_ERROR( ppp.plugin->GetPriority() != plugin->GetPriority(), "FSPLUGINS",
146 "PluginContainer::InsertPlugin(): Plug-in with same priority {} exists",
147 ppp.plugin->GetPriority() )
148
149 return ppp.plugin->GetPriority() < plugin->GetPriority();
150 } ),
151 Slot { plugin, responsibility == lang::Responsibility::Transfer } );
153 }
154
155
156 //==========================================================================================
157 /// Removes the given plug-in from the list of plug-ins.
158 ///
159 /// Responsibility for deletion of removed plug-ins is passed to the remover in case the
160 /// plug-in was inserted with parameter \p{responsibility} set to
161 /// \alib{lang;Responsibility::Transfer}.
162 ///
163 /// @param plugIn The plug-in to be removed.
164 /// @return \c true if the plug-in was removed, else \c false, which indicates that the
165 /// given plug-in was not found.
166 //==========================================================================================
167 bool RemovePlugin( TPlugin* plugIn )
168 {
169 auto it= std::find_if( plugins.begin(), plugins.end(), [plugIn](Slot& pair)
170 {
171 return pair.plugin == plugIn;
172 } );
173 if( it != plugins.end() )
174 {
175 plugins.erase( it );
176 return true;
177 }
178
179 ALIB_WARNING("LANG", "PluginContainer::RemovePlugin(): Plug-in not found for removal.")
180 return false;
181 }
182
183 //==========================================================================================
184 /// Remove the plug-in at the given \p{idx} from the list of plug-ins.
185 ///
186 /// Responsibility for deletion of removed plug-ins is passed to the remover in case the
187 /// plug-in was inserted with parameter \p{responsibility} set to
188 /// \alib{lang;Responsibility::Transfer}.
189 ///
190 /// @param idx The index of the plug-in to remove.
191 //==========================================================================================
193 {
194 ALIB_ASSERT_WARNING( idx < CountPlugins(), "FSPLUGINS",
195 "PluginContainer::RemovePlugin(): Index out of bounds: {} >= {}", idx, CountPlugins() )
196 plugins.erase( plugins.begin() + idx );
197 }
198
199
200 //==========================================================================================
201 /// Remove the plug-in with the given priority.
202 ///
203 /// Responsibility for deletion of removed plug-ins is passed to the remover in case the
204 /// plug-in was inserted with parameter \p{responsibility} set to
205 /// \alib{lang;Responsibility::Transfer}.
206 ///
207 /// @param priority The priority of the plug-in to remove.
208 /// @return \c true if the plug-in was removed, else \c false, which indicates that no
209 /// plug-in with the given priority was found.
210 //==========================================================================================
211 TPlugin* RemovePlugin( TPriorities priority )
212 {
213 TPlugin* plugin= nullptr;
214 plugins.erase( std::remove_if( plugins.begin(), plugins.end(),
215 [priority, &plugin](Slot& entry)
216 {
217 if( entry.priority == priority)
218 {
219 plugin= entry.plugin;
220 return true;
221 }
222 return false;
223 } ),
224 plugins.end() );
225
226 ALIB_ASSERT_WARNING( plugin, "FSPLUGINS", "No Plug-in was removed." )
227
228 return plugin;
229 }
230
231
232 //==========================================================================================
233 /// Checks if any plug-in is attached. This is useful if optional configuration objects
234 /// are used. In case no plug-in was attached (by a third party), the effort to declare and
235 /// search a variable can be omitted.
236 /// @return \c true if this object has any plugin set, \c false otherwise.
237 //==========================================================================================
239 {
240 return CountPlugins() > 0;
241 }
242
243 //==========================================================================================
244 /// Returns the number of plug-ins attached.
245 /// @return The quantity of attached plug-ins.
246 //==========================================================================================
248 {
249 return integer(plugins.size());
250 }
251
252 //==========================================================================================
253 /// Returns the plug-in with the given internal number. Valid numbers are
254 /// 0..[#CountPlugins]. No internal checks for valid plug-in numbers are made.
255 ///
256 /// @param number The number of the plug-in requested.
257 /// @return The plug-in requested.
258 //==========================================================================================
259 TPlugin* GetPlugin( integer number )
260 {
261 return plugins[size_t(number)].plugin;
262 }
263
264 //==========================================================================================
265 /// Returns the priority of the plug-in with the given internal number. Valid numbers are
266 /// 0..[#CountPlugins]. No internal checks for valid plug-in numbers are made.
267 ///
268 /// @param number The number of the plug-in requested.
269 /// @return The priortiy of the plug-in.
270 //==========================================================================================
271 TPriorities GetPriority( integer number )
272 {
273 return plugins[size_t(number)].priority;
274 }
275
276
277 //==========================================================================================
278 /// Returns the plug-in with the given priority. If the plug-in does not exist, \c nullptr
279 /// is returned.
280 ///
281 /// @param priority The priority of the plug-in to return.
282 /// @return The plug-in requested or \c nullptr if not available.
283 //==========================================================================================
284 TPlugin* GetPlugin( TPriorities priority )
285 {
286 auto it = std::find_if( plugins.begin(), plugins.end(),
287 [priority](Slot& pair) { return pair.priority == priority; } );
288 if( it != plugins.end() )
289 return it->plugin;
290 return nullptr;
291 }
292
293 //==========================================================================================
294 /// Same as #GetPlugin, but converts the plug-in found to the template type, which has
295 /// to be explicitly provided with the invocation of this method.
296 ///
297 /// A type-check is performed using standard C++ \c dynamic_cast mechanics.
298 /// If the plugin has a different type, \c nullptr is returned.
299 ///
300 /// @tparam TPluginType The type of the plugin to search.
301 /// @param priority The priority of the plug-in to return.
302 /// @return The plug-in of requested type and priority. \c nullptr if not available.
303 //==========================================================================================
304 template<typename TPluginType>
305 TPluginType* GetPluginTypeSafe( TPriorities priority )
306 {
307 return dynamic_cast<TPluginType*>( GetPlugin( priority ) );
308 }
309
310 //==========================================================================================
311 /// Searches the list of plug-ins for the first found with type \p{TPluginType}.
312 ///
313 /// @tparam TPluginType The type of the plugin to search.
314 /// @return The plug-in of requested type. \c nullptr if not available.
315 //==========================================================================================
316 template<typename TPluginType>
317 TPluginType* GetPluginTypeSafe()
318 {
319 TPluginType* cast= nullptr;
320 for( auto& ppp : plugins )
321 if( (cast= dynamic_cast<TPluginType*>( ppp.plugin )) != nullptr )
322 break;
323
324 return cast;
325 }
326
327}; // class PluginContainer
328
329} // namespace [alib::lang]
330
331
TPlugin * GetPlugin(TPriorities priority)
Definition plugins.inl:284
TPlugin * RemovePlugin(TPriorities priority)
Definition plugins.inl:211
TPriorities PrioritiesType
This exposes the template parameter pTPlugin to the outer world.
Definition plugins.inl:78
void RemovePlugin(integer idx)
Definition plugins.inl:192
TPriorities GetPriority(integer number)
Definition plugins.inl:271
bool RemovePlugin(TPlugin *plugIn)
Definition plugins.inl:167
TPlugin * GetPlugin(integer number)
Definition plugins.inl:259
TPlugin PluginType
This exposes the template parameter pTPlugin to the outer world.
Definition plugins.inl:75
PluginList plugins
The plug-ins we have attached in descending priority order.
Definition plugins.inl:97
void InsertPlugin(TPlugin *plugin, lang::Responsibility responsibility=lang::Responsibility::KeepWithSender)
Definition plugins.inl:129
TPluginType * GetPluginTypeSafe(TPriorities priority)
Definition plugins.inl:305
TPluginType * GetPluginTypeSafe()
Definition plugins.inl:317
std::vector< Slot > PluginList
The list that stores the plugins.
Definition plugins.inl:89
TPriorities PrioritiesType
This exposes the template parameter pTPlugin to the outer world.
Definition plugins.inl:33
PrioritiesType priority
The priority of this plug-in.
Definition plugins.inl:37
TPlugin PluginType
This exposes the template parameter TPlugin to the outer world.
Definition plugins.inl:30
PrioritiesType GetPriority() const
Definition plugins.inl:47
Plugin(PrioritiesType pPriority)
Definition plugins.inl:41
#define ALIB_WARNINGS_IGNORE_UNUSED_LAMBDA_CAPTURE
Definition alib.inl:673
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:705
#define ALIB_WARNING(domain,...)
Definition alib.inl:1046
#define ALIB_STATIC_ASSERT(CondVariable, Cond, Message)
Definition alib.inl:954
#define ALIB_ASSERT_WARNING(cond, domain,...)
Definition alib.inl:1050
#define ALIB_EXPORT
Definition alib.inl:488
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
platform_specific integer
Definition integers.inl:32
@ KeepWithSender
Keeps responsibility, e.g., when passing an object.
Type definition for elements of the list of plug-ins with their priority.
Definition plugins.inl:82
TPlugin * plugin
The plug-in.
Definition plugins.inl:83