Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
ServiceBuilder.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* ServiceBuilder.h (C) 2000-2023 */
9/* */
10/* Utility class for instantiating a service. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_CORE_SERVICEBUILDER_H
13#define ARCANE_CORE_SERVICEBUILDER_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/Array.h"
18#include "arcane/utils/TraceInfo.h"
19#include "arcane/utils/FatalErrorException.h"
20#include "arcane/utils/ParallelFatalErrorException.h"
21
22#include "arcane/core/ISession.h"
23#include "arcane/core/ISubDomain.h"
24#include "arcane/core/IApplication.h"
25#include "arcane/core/IMesh.h"
26#include "arcane/core/ICaseOptions.h"
27#include "arcane/core/IFactoryService.h"
28#include "arcane/core/ServiceFinder2.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane
34{
35namespace AxlOptionsBuilder
36{
37 class Document;
38}
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43/*!
44 * \brief Properties for service creation.
45 *
46 * These are flags used with the binary OR operator (|).
47 */
49{
50 //! No specific property.
52 //! Allows the service to be absent.
54 //! Indicates that all processes perform the same operation.
56};
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61/*!
62 * \ingroup Service
63 * \brief Utility class for instantiating a service of a given interface.
64 *
65 * This class allows searching for all available services
66 * implementing the \a InterfaceType interface passed as a template parameter.
67 *
68 * This class replaces older classes that allowed service creation,
69 * namely ServiceFinderT, ServiceFinder2T, and FactoryT.
70 *
71 * There are three constructors depending on whether you want to instantiate
72 * a subdomain, a session, or an application service. Generally,
73 * it is a subdomain service; the last two categories
74 * are rather used for internal Arcane services.
75 *
76 * The following example creates a subdomain service implementing
77 * the \a IMyInterface interface with the name \a TOTO:
78 * \code
79 * ISubDomain* sd = ...
80 * ServiceBuilder<IMyInterface> builder(sd);
81 * ServiceRef<IMyInterface> iservice = builder.createReference("TOTO");
82 * ...
83 * \endcode
84 *
85 * The returned instance is managed by a reference counter and is destroyed
86 * as soon as there are no more references to it.
87 * By default, createInstance() throws an exception if the service is not
88 * found, unless the \a SB_AllowNull property is specified.
89 * If the \a SB_Collective property is true, the exception thrown is of type
90 * ParallelFatalErrorException; otherwise, it is of type FatalErrorException.
91 * This is useful if you are sure
92 * that all processes will perform the same operation. In this case,
93 * this allows only one error message to be generated and the code to stop
94 * cleanly.
95 *
96 * It is also possible to retrieve a singleton instance of a service,
97 * via getSingleton(). The available singleton instances
98 * are referenced in the code configuration file (see \ref arcanedoc_core_types_codeconfig).
99 */
100template <typename InterfaceType>
102{
103 public:
104
105 //! Instantiation to create a subdomain service.
107 : m_service_finder(sd->application(), ServiceBuildInfoBase(sd))
108 {}
109 //! Instantiation to create a subdomain service associated with the \a mesh_handle
110 ServiceBuilder(const MeshHandle& mesh_handle)
111 : m_service_finder(mesh_handle.application(), ServiceBuildInfoBase(mesh_handle))
112 {}
113 //! Instantiation to create a session service.
115 : m_service_finder(session->application(), ServiceBuildInfoBase(session))
116 {}
117 //! Instantiation to create an application service.
119 : m_service_finder(app, ServiceBuildInfoBase(app))
120 {}
121 //! Instantiation to create a dataset options service
123 : m_service_finder(app, ServiceBuildInfoBase(_arcaneDeprecatedGetSubDomain(opt), opt))
124 {}
125
126 ~ServiceBuilder() {}
127
128 public:
129
130 /*!
131 * \brief Creates an instance implementing the \a InterfaceType interface.
132 *
133 * The instance is created using the factory registered under the name \a name.
134 *
135 * By default, an exception is thrown if the specified service is not found.
136 * It is possible to change this behavior by specifying SB_AllowNull in \a properties,
137 * in which case the function returns a null pointer if the specified service does not exist.
138 */
139 Ref<InterfaceType>
141 {
142 Ref<InterfaceType> mf = m_service_finder.createReference(name);
143 if (!mf) {
144 if (properties & SB_AllowNull)
145 return {};
146 _throwFatal(name, properties);
147 }
148 return mf;
149 }
150
151 /*!
152 * \brief Creates an instance implementing the \a InterfaceType interface.
153 *
154 * The instance is created using the factory registered under the name \a name.
155 * The returned pointer must be deallocated using delete.
156 *
157 * It is possible to specify the \a mesh on which the service will reside.
158 * This is only useful for subdomain services. For session or application services,
159 * this argument is not used.
160 *
161 * By default, an exception is thrown if the specified service is not found.
162 * It is possible to change this behavior by specifying SB_AllowNull in \a properties,
163 * in which case the function returns a null pointer if the specified service does not exist.
164 */
166 createReference(const String& name, IMesh* mesh,
168 {
169 Ref<InterfaceType> mf = m_service_finder.createReference(name, mesh);
170 if (!mf) {
171 if (properties & SB_AllowNull)
172 return {};
173 _throwFatal(name, properties);
174 }
175 return mf;
176 }
177
178 /*!
179 * \brief Creates an instance of every service that implements \a InterfaceType.
180 *
181 * The created instances are stored in \a instances. The caller must
182 * destroy them using the delete operator once they are no longer useful.
183 */
185 {
186 return m_service_finder.createAll();
187 }
188
189 /*!
190 * \brief Singleton instance of the service implementing the \a InterfaceType interface.
191 *
192 * The returned instance must not be destroyed.
193 *
194 * By default, an exception is thrown if the specified service is not found.
195 * It is possible to change this behavior by specifying SB_AllowNull in \a properties,
196 * in which case the function returns a null pointer if the specified service does not exist.
197 */
198 InterfaceType* getSingleton(eServiceBuilderProperties properties = SB_None)
199 {
200 InterfaceType* mf = m_service_finder.getSingleton();
201 if (!mf) {
202 if (properties & SB_AllowNull)
203 return 0;
204 _throwFatal(properties);
205 }
206 return mf;
207 }
208
209 /*!
210 * \brief Creates an instance implementing the \a InterfaceType interface.
211 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
212 */
213 static Ref<InterfaceType>
216 {
217 return createReference(sd, name, 0, properties);
218 }
219
220 /*!
221 * \brief Creates an instance implementing the \a InterfaceType interface.
222 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
223 */
224 static Ref<InterfaceType>
225 createReference(ISession* session, const String& name,
227 {
229 {
230 ServiceBuilder sb(session);
231 it = sb.createReference(name, properties);
232 }
233 return it;
234 }
235
236 /*!
237 * \brief Creates an instance implementing the \a InterfaceType interface.
238 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
239 */
240 static Ref<InterfaceType>
243 {
245 {
246 ServiceBuilder sb(app);
247 it = sb.createReference(name, properties);
248 }
249 return it;
250 }
251
252 /*!
253 * \brief Creates an instance implementing the \a InterfaceType interface.
254 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
255 */
256 static Ref<InterfaceType>
257 createReference(ISubDomain* sd, const String& name, IMesh* mesh,
259 {
261 {
262 ServiceBuilder sb(sd);
263 it = sb.createReference(name, mesh, properties);
264 }
265 return it;
266 }
267
268 //! Fills \a names with the names of services available to instantiate this interface
270 {
271 m_service_finder.getServicesNames(names);
272 }
273
274 public:
275
276 /*!
277 * \brief Creates an instance of every service that implements \a InterfaceType.
278 *
279 * The created instances are stored in \a instances. The caller must
280 * destroy them using the delete operator once they are no longer needed.
281 *
282 * \deprecated Use the overload that returns an array of references.
283 */
284 ARCCORE_DEPRECATED_2019("use createAllInstances(Array<Ref<InterfaceType>>) instead")
285 void createAllInstances(Array<InterfaceType*>& instances)
286 {
287 m_service_finder.createAll(instances);
288 }
289
290 /*!
291 * \brief Creates an instance implementing the interface \a InterfaceType.
292 *
293 * The instance is created using the factory registered under the name \a name.
294 * The returned pointer must be deallocated using delete.
295 *
296 * By default, an exception is thrown if the specified service is not found.
297 * It is possible to change this behavior by specifying SB_AllowNull in \a properties
298 * in which case the function returns a null pointer if the specified service does not exist.
299 *
300 * \deprecated Use createReference() instead.
301 */
302 ARCCORE_DEPRECATED_2019("Use createReference() instead")
303 InterfaceType* createInstance(const String& name, eServiceBuilderProperties properties = SB_None)
304 {
305 InterfaceType* mf = m_service_finder.create(name);
306 if (!mf) {
307 if (properties & SB_AllowNull)
308 return 0;
309 _throwFatal(name, properties);
310 }
311 return mf;
312 }
313
314 /*!
315 * \brief Creates an instance implementing the interface \a InterfaceType.
316 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
317 * \deprecated Use createReference() instead.
318 */
319 ARCCORE_DEPRECATED_2019("Use createReference() instead")
320 static InterfaceType*
323 {
324 return createInstance(sd, name, 0, properties);
325 }
326
327 /*!
328 * \brief Creates an instance implementing the interface \a InterfaceType.
329 *
330 * The instance is created using the factory registered under the name \a name.
331 * The returned pointer must be deallocated using delete.
332 *
333 * It is possible to specify the mesh \a mesh on which the service will rely.
334 * This is only useful for subdomain services. For session
335 * or application services, this argument is not used.
336 *
337 * By default, an exception is thrown if the specified service is not found.
338 * It is possible to change this behavior by specifying SB_AllowNull in \a properties
339 * in which case the function returns a null pointer if the specified service does not exist.
340 *
341 * \deprecated Use createReference() instead.
342 */
343 ARCCORE_DEPRECATED_2019("Use createReference() instead")
344 InterfaceType* createInstance(const String& name, IMesh* mesh,
346 {
347 InterfaceType* mf = m_service_finder.create(name, mesh);
348 if (!mf) {
349 if (properties & SB_AllowNull)
350 return 0;
351 _throwFatal(name, properties);
352 }
353 return mf;
354 }
355
356 /*!
357 * \brief Creates an instance implementing the interface \a InterfaceType.
358 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
359 */
360 ARCCORE_DEPRECATED_2019("Use createReference() instead")
361 static InterfaceType* createInstance(ISession* session, const String& name,
363 {
364 InterfaceType* it = 0;
365 {
366 ServiceBuilder sb(session);
367 it = sb.createInstance(name, properties);
368 }
369 return it;
370 }
371
372 /*!
373 * \brief Creates an instance implementing the interface \a InterfaceType.
374 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
375 */
376 ARCCORE_DEPRECATED_2019("Use createReference() instead")
377 static InterfaceType* createInstance(IApplication* app, const String& name,
379 {
380 InterfaceType* it = 0;
381 {
382 ServiceBuilder sb(app);
383 it = sb.createInstance(name, properties);
384 }
385 return it;
386 }
387
388 /*!
389 * \brief Creates an instance implementing the interface \a InterfaceType.
390 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
391 */
392 ARCCORE_DEPRECATED_2019("Use createReference() instead")
393 static InterfaceType* createInstance(ISubDomain* sd, const String& name, IMesh* mesh,
395 {
396 InterfaceType* it = 0;
397 {
398 ServiceBuilder sb(sd);
399 it = sb.createInstance(name, mesh, properties);
400 }
401 return it;
402 }
403
404 private:
405
407
408 private:
409
410 String _getErrorMessage(String wanted_name)
411 {
412 StringUniqueArray valid_names;
413 m_service_finder.getServicesNames(valid_names);
414 if (valid_names.size() != 0)
415 return String::format("no service named '{0}' found (valid values = {1})",
416 wanted_name, String::join(", ", valid_names));
417 // No service available
418 return String::format("no service named '{0}' found and no implementation available",
419 wanted_name);
420 }
421
422 void _throwFatal(const String& name, eServiceBuilderProperties properties)
423 {
424 String err_msg = _getErrorMessage(name);
425 if (properties & SB_Collective)
426 throw ParallelFatalErrorException(A_FUNCINFO, err_msg);
427 else
428 throw FatalErrorException(A_FUNCINFO, err_msg);
429 }
430 void _throwFatal(eServiceBuilderProperties properties)
431 {
432 String err_msg = "No singleton service found for that interface";
433 if (properties & SB_Collective)
434 throw ParallelFatalErrorException(A_FUNCINFO, err_msg);
435 else
436 throw FatalErrorException(A_FUNCINFO, err_msg);
437 }
438};
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442/*!
443 * \internal
444 */
445class ARCANE_CORE_EXPORT ServiceBuilderWithOptionsBase
446{
447 protected:
448
449 ServiceBuilderWithOptionsBase(ICaseMng* cm)
450 : m_case_mng(cm)
451 {
452 }
453
454 protected:
455
456 ReferenceCounter<ICaseOptions> _buildCaseOptions(const AxlOptionsBuilder::Document& options_doc) const;
457 IApplication* _application() const;
458 void _readOptions(ICaseOptions* opt) const;
459
460 protected:
461
462 ICaseMng* m_case_mng = nullptr;
463};
464
465/*---------------------------------------------------------------------------*/
466/*---------------------------------------------------------------------------*/
467
468/*!
469 * \brief Utility class for instantiating a service of a given interface
470 * with options.
471 *
472 * \warning Experimental API. Do not use outside of %Arcane
473 */
474template <typename InterfaceType>
475class ServiceBuilderWithOptions
476: private ServiceBuilderWithOptionsBase
477{
478 public:
479
480 ServiceBuilderWithOptions(ICaseMng* cm)
481 : ServiceBuilderWithOptionsBase(cm)
482 {}
483
484 public:
485
487 createReference(const String& service_name, const AxlOptionsBuilder::Document& options_doc,
489 {
490 ReferenceCounter<ICaseOptions> opt(_buildCaseOptions(options_doc));
491 ServiceBuilder<InterfaceType> sbi(_application(), opt.get());
492 Ref<InterfaceType> s = sbi.createReference(service_name, properties);
493 if (s.get()) {
494 _readOptions(opt.get());
495 }
496 return s;
497 }
498};
499
500/*---------------------------------------------------------------------------*/
501/*---------------------------------------------------------------------------*/
502
503} // End namespace Arcane
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
508#endif
Integer size() const
Number of elements in the vector.
Base class for 1D data vectors.
Data set 'ServiceInstance' option.
T * get() const
Returns the object referenced by the instance.
Application interface.
Case manager interface.
Definition ICaseMng.h:57
Interface for a case execution session.
Definition ISession.h:38
Interface of the subdomain manager.
Definition ISubDomain.h:75
Handle on a mesh.
Definition MeshHandle.h:48
InstanceType * get() const
Associated instance or nullptr if none.
Reference to an instance.
Encapsulation of a pointer with a reference counter.
Information for creating a service.
Utility class for instantiating a service of a given interface.
UniqueArray< Ref< InterfaceType > > createAllInstances()
Creates an instance of every service that implements InterfaceType.
static Ref< InterfaceType > createReference(ISession *session, const String &name, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
Ref< InterfaceType > createReference(const String &name, IMesh *mesh, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
ServiceBuilder(ISubDomain *sd)
Instantiation to create a subdomain service.
static Ref< InterfaceType > createReference(ISubDomain *sd, const String &name, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
Ref< InterfaceType > createReference(const String &name, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
static Ref< InterfaceType > createReference(ISubDomain *sd, const String &name, IMesh *mesh, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
InterfaceType * createInstance(const String &name, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the interface InterfaceType.
static Ref< InterfaceType > createReference(IApplication *app, const String &name, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
ServiceBuilder(ISession *session)
Instantiation to create a session service.
InterfaceType * getSingleton(eServiceBuilderProperties properties=SB_None)
Singleton instance of the service implementing the InterfaceType interface.
ServiceBuilder(const MeshHandle &mesh_handle)
Instantiation to create a subdomain service associated with the mesh_handle.
void getServicesNames(Array< String > &names) const
Fills names with the names of services available to instantiate this interface.
ServiceBuilder(IApplication *app)
Instantiation to create an application service.
ServiceBuilder(IApplication *app, ICaseOptions *opt)
Instantiation to create a dataset options service.
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
eServiceBuilderProperties
Properties for service creation.
@ SB_Collective
Indicates that all processes perform the same operation.
@ SB_AllowNull
Allows the service to be absent.
@ SB_None
No specific property.
UniqueArray< String > StringUniqueArray
Dynamic 1D array of strings.
Definition UtilsTypes.h:359