Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ServiceBuilder.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* Classe utilitaire pour instantier un 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{
37class Document;
38}
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42/*!
43 * \brief Propriétés pour la création de service.
44 *
45 * Il s'agit de drapeaux qui s'utilisent avec l'opérateur ou binaire (|)
46 */
48{
49 //! Aucune propriété particulière
51 //! Autorise l'absence du service
53 //! Indique que tous les processus font la même opération
55};
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59/*!
60 * \ingroup Service
61 * \brief Classe utilitaire pour instantier un service d'une interface donnée.
62 *
63 * Cette classe permet de rechercher l'ensemble des services disponibles
64 * et implémentant l'interface \a InterfaceType passée en paramètre template.
65 *
66 * Cette classe remplace les anciennes classes qui permettaient de créer
67 * des services, à savoir ServiceFinderT, ServiceFinder2T et FactoryT.
68 *
69 * Il existe trois constructeurs suivant que l'on souhaite instantier
70 * un service du sous-domaine, de la session ou de l'application. En général,
71 * il s'agit d'un service de sous-domaine, les deux dernières catégories
72 * étant plutôt utilisées pour les services internes à Arcane.
73 *
74 * L'exemple suivant créé un service de sous-domaine implémentant
75 * l'interface \a IMyInterface et de nom \a TOTO:
76 * \code
77 * ISubDomain* sd = ...
78 * ServiceBuilder<IMyInterface> builder(sd);
79 * ServiceRef<IMyInterface> iservice = builder.createReference("TOTO");
80 * ...
81 * \endcode
82 *
83 * L'instance retournée est gérée par compteur de référence et est détruite
84 * dès qu'il n'y a plus de référence dessus.
85 * Par défaut, createInstance() lève une exception si le service n'est pas
86 * trouvé, sauf si la propriété \a SB_AllowNull est spécifiée..
87 * Si la propriété \a SB_Collective est vrai, l'exception levée est du type
88 * ParallelFatalErrorException, sinon elle du type FatalErrorException.
89 * Cela est utile si on est sur
90 * que tous les processus vont faire la même opération. Dans ce cas,
91 * cela permet de ne générer qu'un seul message d'erreur et d'arrêter
92 * le code proprement.
93 *
94 * Il est aussi possible de récupérer une instance singleton d'un service,
95 * via getSingleton(). Les instances singletons qui sont disponibles
96 * sont référencées dans le fichier de configuration du code (voir \ref arcanedoc_core_types_codeconfig).
97 */
98template<typename InterfaceType>
100{
101 public:
102
103 //! Instantiation pour créer un service d'un sous-domaine.
105 : m_service_finder(sd->application(),ServiceBuildInfoBase(sd))
106 {}
107 //! Instantiation pour créer un service de sous-domaine associé au maillage \a mesh_handle
108 ServiceBuilder(const MeshHandle& mesh_handle)
109 : m_service_finder(mesh_handle.application(),ServiceBuildInfoBase(mesh_handle))
110 {}
111 //! Instantiation pour créer un service d'une session.
113 : m_service_finder(session->application(),ServiceBuildInfoBase(session))
114 {}
115 //! Instantiation pour créer un service de l'application.
117 : m_service_finder(app,ServiceBuildInfoBase(app))
118 {}
119 //! Instantiation pour créer un service d'option du jeu de données
121 : m_service_finder(app,ServiceBuildInfoBase(_arcaneDeprecatedGetSubDomain(opt),opt))
122 {}
123
124 ~ServiceBuilder(){ }
125
126 public:
127
128 /*!
129 * \brief Créé une instance implémentant l'interface \a InterfaceType.
130 *
131 * L'instance est créée avec la fabrique enregistrée sous le nom \a name.
132 *
133 * Par défaut, une exception est levée si le service spécifiée n'est pas trouvé.
134 * Il est possible de changer ce comportement en spécifiant SB_AllowNull dans \a properties
135 * auquel cas la fonction retourne un pointeur nul si le service spécifié n'existe pas.
136 */
137 Ref<InterfaceType>
139 {
140 Ref<InterfaceType> mf = m_service_finder.createReference(name);
141 if (!mf){
142 if (properties & SB_AllowNull)
143 return {};
144 _throwFatal(name,properties);
145 }
146 return mf;
147 }
148
149 /*!
150 * \brief Créé une instance implémentant l'interface \a InterfaceType.
151 *
152 * L'instance est créée avec la fabrique enregistrée sous le nom \a name.
153 * Le pointeur retourné doit être désalloué par delete.
154 *
155 * Il est possible de spécifier le maillage \a mesh sur lequel reposera le service.
156 * Cela n'est utile que pour les services de sous-domaine. Pour les services
157 * de session ou d'application, cet argument n'est pas utilisé.
158 *
159 * Par défaut, une exception est levée si le service spécifiée n'est pas trouvé.
160 * Il est possible de changer ce comportement en spécifiant SB_AllowNull dans \a properties
161 * auquel cas la fonction retourne un pointeur nul si le service spécifié n'existe pas.
162 */
163 Ref<InterfaceType>
164 createReference(const String& name,IMesh* mesh,
166 {
167 Ref<InterfaceType> mf = m_service_finder.createReference(name,mesh);
168 if (!mf){
169 if (properties & SB_AllowNull)
170 return {};
171 _throwFatal(name,properties);
172 }
173 return mf;
174 }
175
176 /*!
177 * \brief Créé une instance de chaque service qui implémente \a InterfaceType.
178 *
179 * Les instances créées sont rangées dans \a instances. L'appelant doit les
180 * détruire via l'opérateur delete une fois qu'elles ne sont plus utiles.
181 */
183 {
184 return m_service_finder.createAll();
185 }
186
187 /*!
188 * \brief Instance singleton du service implémentant l'interface \a InterfaceType.
189 *
190 * L'instance retournée ne doit pas être détruite.
191 *
192 * Par défaut, une exception est levée si le service spécifiée n'est pas trouvé.
193 * Il est possible de changer ce comportement en spécifiant SB_AllowNull dans \a properties
194 * auquel cas la fonction retourne un pointeur nul si le service spécifié n'existe pas.
195 */
197 {
198 InterfaceType* mf = m_service_finder.getSingleton();
199 if (!mf){
200 if (properties & SB_AllowNull)
201 return 0;
202 _throwFatal(properties);
203 }
204 return mf;
205 }
206
207 /*!
208 * \brief Créé une instance implémentant l'interface \a InterfaceType.
209 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
210 */
211 static Ref<InterfaceType>
214 {
215 return createReference(sd,name,0,properties);
216 }
217
218 /*!
219 * \brief Créé une instance implémentant l'interface \a InterfaceType.
220 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
221 */
222 static Ref<InterfaceType>
223 createReference(ISession* session,const String& name,
225 {
226 Ref<InterfaceType> it;
227 {
228 ServiceBuilder sb(session);
229 it = sb.createReference(name,properties);
230 }
231 return it;
232 }
233
234 /*!
235 * \brief Créé une instance implémentant l'interface \a InterfaceType.
236 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
237 */
238 static Ref<InterfaceType>
241 {
242 Ref<InterfaceType> it;
243 {
244 ServiceBuilder sb(app);
245 it = sb.createReference(name,properties);
246 }
247 return it;
248 }
249
250 /*!
251 * \brief Créé une instance implémentant l'interface \a InterfaceType.
252 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
253 */
254 static Ref<InterfaceType>
255 createReference(ISubDomain* sd,const String& name,IMesh* mesh,
257 {
258 Ref<InterfaceType> it;
259 {
260 ServiceBuilder sb(sd);
261 it = sb.createReference(name,mesh,properties);
262 }
263 return it;
264 }
265
266 //! Remplit \a names avec les noms des services disponibles pour instantier cette interface
268 {
269 m_service_finder.getServicesNames(names);
270 }
271
272 public:
273 /*!
274 * \brief Créé une instance de chaque service qui implémente \a InterfaceType.
275 *
276 * Les instances créées sont rangées dans \a instances. L'appelant doit les
277 * détruire via l'opérateur delete une fois qu'elles ne sont plus utiles.
278 *
279 * \deprecated Utilise la surcharge qui retourne un tableau de références.
280 */
281 ARCCORE_DEPRECATED_2019("use createAllInstances(Array<Ref<InterfaceType>>) instead")
282 void createAllInstances(Array<InterfaceType*>& instances)
283 {
284 m_service_finder.createAll(instances);
285 }
286
287 /*!
288 * \brief Créé une instance implémentant l'interface \a InterfaceType.
289 *
290 * L'instance est créée avec la fabrique enregistrée sous le nom \a name.
291 * Le pointeur retourné doit être désalloué par delete.
292 *
293 * Par défaut, une exception est levée si le service spécifiée n'est pas trouvé.
294 * Il est possible de changer ce comportement en spécifiant SB_AllowNull dans \a properties
295 * auquel cas la fonction retourne un pointeur nul si le service spécifié n'existe pas.
296 *
297 * \deprecated Utilise createReference() à la place.
298 */
299 ARCCORE_DEPRECATED_2019("Use createReference() instead")
300 InterfaceType* createInstance(const String& name,eServiceBuilderProperties properties=SB_None)
301 {
302 InterfaceType* mf = m_service_finder.create(name);
303 if (!mf){
304 if (properties & SB_AllowNull)
305 return 0;
306 _throwFatal(name,properties);
307 }
308 return mf;
309 }
310
311 /*!
312 * \brief Créé une instance implémentant l'interface \a InterfaceType.
313 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
314 * \deprecated Utilise createReference() à la place.
315 */
316 ARCCORE_DEPRECATED_2019("Use createReference() instead")
317 static InterfaceType*
320 {
321 return createInstance(sd,name,0,properties);
322 }
323
324 /*!
325 * \brief Créé une instance implémentant l'interface \a InterfaceType.
326 *
327 * L'instance est créée avec la fabrique enregistrée sous le nom \a name.
328 * Le pointeur retourné doit être désalloué par delete.
329 *
330 * Il est possible de spécifier le maillage \a mesh sur lequel reposera le service.
331 * Cela n'est utile que pour les services de sous-domaine. Pour les services
332 * de session ou d'application, cet argument n'est pas utilisé.
333 *
334 * Par défaut, une exception est levée si le service spécifiée n'est pas trouvé.
335 * Il est possible de changer ce comportement en spécifiant SB_AllowNull dans \a properties
336 * auquel cas la fonction retourne un pointeur nul si le service spécifié n'existe pas.
337 *
338 * \deprecated Utilise createReference() à la place.
339 */
340 ARCCORE_DEPRECATED_2019("Use createReference() instead")
341 InterfaceType* createInstance(const String& name,IMesh* mesh,
343 {
344 InterfaceType* mf = m_service_finder.create(name,mesh);
345 if (!mf){
346 if (properties & SB_AllowNull)
347 return 0;
348 _throwFatal(name,properties);
349 }
350 return mf;
351 }
352
353 /*!
354 * \brief Créé une instance implémentant l'interface \a InterfaceType.
355 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
356 */
357 ARCCORE_DEPRECATED_2019("Use createReference() instead")
358 static InterfaceType* createInstance(ISession* session,const String& name,
360 {
361 InterfaceType* it = 0;
362 {
363 ServiceBuilder sb(session);
364 it = sb.createInstance(name,properties);
365 }
366 return it;
367 }
368
369 /*!
370 * \brief Créé une instance implémentant l'interface \a InterfaceType.
371 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
372 */
373 ARCCORE_DEPRECATED_2019("Use createReference() instead")
374 static InterfaceType* createInstance(IApplication* app,const String& name,
376 {
377 InterfaceType* it = 0;
378 {
379 ServiceBuilder sb(app);
380 it = sb.createInstance(name,properties);
381 }
382 return it;
383 }
384
385 /*!
386 * \brief Créé une instance implémentant l'interface \a InterfaceType.
387 * \sa createInstance(const String& name,eServiceBuilderProperties properties)
388 */
389 ARCCORE_DEPRECATED_2019("Use createReference() instead")
390 static InterfaceType* createInstance(ISubDomain* sd,const String& name,IMesh* mesh,
392 {
393 InterfaceType* it = 0;
394 {
395 ServiceBuilder sb(sd);
396 it = sb.createInstance(name,mesh,properties);
397 }
398 return it;
399 }
400
401 private:
402
404
405 private:
406
407 String _getErrorMessage(String wanted_name)
408 {
409 StringUniqueArray valid_names;
410 m_service_finder.getServicesNames(valid_names);
411 if (valid_names.size()!=0)
412 return String::format("no service named '{0}' found (valid values = {1})",
413 wanted_name,String::join(", ",valid_names));
414 // Aucun service disponible
415 return String::format("no service named '{0}' found and no implementation available",
416 wanted_name);
417 }
418
419 void _throwFatal(const String& name,eServiceBuilderProperties properties)
420 {
421 String err_msg = _getErrorMessage(name);
422 if (properties & SB_Collective)
423 throw ParallelFatalErrorException(A_FUNCINFO,err_msg);
424 else
425 throw FatalErrorException(A_FUNCINFO,err_msg);
426 }
427 void _throwFatal(eServiceBuilderProperties properties)
428 {
429 String err_msg = "No singleton service found for that interface";
430 if (properties & SB_Collective)
431 throw ParallelFatalErrorException(A_FUNCINFO,err_msg);
432 else
433 throw FatalErrorException(A_FUNCINFO,err_msg);
434 }
435};
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439/*!
440 * \internal
441 */
442class ARCANE_CORE_EXPORT ServiceBuilderWithOptionsBase
443{
444 protected:
445
447 : m_case_mng(cm)
448 {
449 }
450
451 protected:
452
453 ReferenceCounter<ICaseOptions> _buildCaseOptions(const AxlOptionsBuilder::Document& options_doc) const;
454 IApplication* _application() const;
455 void _readOptions(ICaseOptions* opt) const;
456
457 protected:
458
459 ICaseMng* m_case_mng = nullptr;
460};
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464/*!
465 * \brief Classe utilitaire pour instantier un service d'une interface donnée
466 * avec des options.
467 *
468 * \warning API expérimentale. Ne pas utiliser en dehors de %Arcane
469 */
470template<typename InterfaceType>
473{
474 public:
475
477
478 public:
479
480 Ref<InterfaceType>
481 createReference(const String& service_name,const AxlOptionsBuilder::Document& options_doc,
483 {
484 ReferenceCounter<ICaseOptions> opt(_buildCaseOptions(options_doc));
485 ServiceBuilder<InterfaceType> sbi(_application(),opt.get());
486 Ref<InterfaceType> s = sbi.createReference(service_name,properties);
487 if (s.get()){
488 _readOptions(opt.get());
489 }
490 return s;
491 }
492};
493
494/*---------------------------------------------------------------------------*/
495/*---------------------------------------------------------------------------*/
496
497} // End namespace Arcane
498
499/*---------------------------------------------------------------------------*/
500/*---------------------------------------------------------------------------*/
501
502#endif
503
Option 'ServiceInstance' du jeu de données.
Interface de l'application.
Interface du gestionnaire de cas.
Definition ICaseMng.h:56
Interface d'une session d'exécution d'un cas.
Definition ISession.h:44
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
Handle sur un maillage.
Definition MeshHandle.h:47
Informations pour créer un service.
Classe utilitaire pour instantier un service d'une interface donnée avec des options.
Classe utilitaire pour instantier un service d'une interface donnée.
UniqueArray< Ref< InterfaceType > > createAllInstances()
Créé une instance de chaque service qui implémente InterfaceType.
static Ref< InterfaceType > createReference(ISession *session, const String &name, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
Ref< InterfaceType > createReference(const String &name, IMesh *mesh, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
ServiceBuilder(ISubDomain *sd)
Instantiation pour créer un service d'un sous-domaine.
static Ref< InterfaceType > createReference(ISubDomain *sd, const String &name, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
Ref< InterfaceType > createReference(const String &name, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
static Ref< InterfaceType > createReference(ISubDomain *sd, const String &name, IMesh *mesh, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
InterfaceType * createInstance(const String &name, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
static Ref< InterfaceType > createReference(IApplication *app, const String &name, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
ServiceBuilder(ISession *session)
Instantiation pour créer un service d'une session.
InterfaceType * getSingleton(eServiceBuilderProperties properties=SB_None)
Instance singleton du service implémentant l'interface InterfaceType.
ServiceBuilder(const MeshHandle &mesh_handle)
Instantiation pour créer un service de sous-domaine associé au maillage mesh_handle.
void getServicesNames(Array< String > &names) const
Remplit names avec les noms des services disponibles pour instantier cette interface.
ServiceBuilder(IApplication *app)
Instantiation pour créer un service de l'application.
ServiceBuilder(IApplication *app, ICaseOptions *opt)
Instantiation pour créer un service d'option du jeu de données.
Integer size() const
Nombre d'éléments du vecteur.
Classe de base des vecteurs 1D de données.
T * get() const
Retourne l'objet référé par l'instance.
Encapsulation d'un pointeur avec compteur de référence.
Chaîne de caractères unicode.
Vecteur 1D de données avec sémantique par valeur (style STL).
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
eServiceBuilderProperties
Propriétés pour la création de service.
@ SB_Collective
Indique que tous les processus font la même opération.
@ SB_AllowNull
Autorise l'absence du service.
@ SB_None
Aucune propriété particulière.