Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
GenericRegisterer.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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/* GenericRegisterer.h (C) 2000-2022 */
9/* */
10/* Enregistreur générique de types globaux. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_GENERICREGISTERER_H
13#define ARCANE_UTILS_GENERICREGISTERER_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
18
19/*---------------------------------------------------------------------------*/
20/*---------------------------------------------------------------------------*/
21
22namespace Arcane
23{
24
25class ARCANE_UTILS_EXPORT GenericRegistererBase
26{
27 protected:
28
29 [[noreturn]] void doErrorConflict();
30 [[noreturn]] void doErrorNonZeroCount();
31};
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35/*!
36 * \brief Classe template pour gérer une liste globale permettant d'enregistrer
37 * des fabriques.
38 *
39 * Cette classe utilise le Curiously recurring template pattern (CRTP). Le
40 * paramètre template doit être la classe dérivée et doit avoir une méthode
41 * globalRegistererInfo() comme suit:
42 * \code
43 * class MyRegisterer
44 * : public GenericRegisterer<MyRegisterer>
45 * {
46 * public:
47 * GenericRegisterer<MyRegisterer>::Info& registererInfo();
48 * };
49 * \endcode
50 */
51template <typename Type>
54{
55 protected:
56
57 class Info
58 {
60
61 public:
62
63 Type* firstRegisterer() const { return m_first_registerer; }
64 Int32 nbRegisterer() const { return m_nb_registerer; }
65
66 private:
67
68 Type* m_first_registerer = nullptr;
69 Int32 m_nb_registerer = 0;
70 };
71
72 public:
73
74 using InstanceType = Type;
75
76 public:
77
78 GenericRegisterer() noexcept
79 {
80 _init();
81 }
82
83 public:
84
85 //! Instance précédente (nullptr si la première)
86 InstanceType* previousRegisterer() const { return m_previous; }
87
88 //! Instance suivante (nullptr si la dernière)
89 InstanceType* nextRegisterer() const { return m_next; }
90
91 public:
92
93 //! Accès au premier élément de la chaine d'enregistreur
94 static InstanceType* firstRegisterer()
95 {
96 return Type::registererInfo().firstRegisterer();
97 }
98
99 //! Nombre d'enregisteur de service dans la chaine
100 static Integer nbRegisterer()
101 {
102 return Type::registererInfo().nbRegisterer();
103 }
104
105 private:
106
107 InstanceType* m_previous = nullptr;
108 InstanceType* m_next = nullptr;
109
110 private:
111
112 void _init() noexcept
113 {
114 Info& reg_info = Type::registererInfo();
115 Type* current_instance = static_cast<Type*>(this);
116 // ATTENTION: Cette méthode est appelée depuis un constructeur global
117 // (donc avant le main()) et il ne faut pas faire d'exception dans ce code.
118 InstanceType* first = reg_info.firstRegisterer();
119 if (!first) {
120 reg_info.m_first_registerer = current_instance;
121 m_previous = nullptr;
122 m_next = nullptr;
123 }
124 else {
125 InstanceType* next = first->nextRegisterer();
126 m_next = first;
127 reg_info.m_first_registerer = current_instance;
128 if (next)
129 next->m_previous = current_instance;
130 }
131 ++reg_info.m_nb_registerer;
132
133 // Check integrity
134 auto* p = reg_info.firstRegisterer();
135 Integer count = reg_info.nbRegisterer();
136 while (p && count > 0) {
137 p = p->nextRegisterer();
138 --count;
139 }
140 if (p) {
141 doErrorConflict();
142 }
143 else if (count > 0) {
144 doErrorNonZeroCount();
145 }
146 }
147};
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152} // End namespace Arcane
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157#endif
Fichier de configuration d'Arcane.
Classe template pour gérer une liste globale permettant d'enregistrer des fabriques.
static InstanceType * firstRegisterer()
Accès au premier élément de la chaine d'enregistreur.
static Integer nbRegisterer()
Nombre d'enregisteur de service dans la chaine.
InstanceType * nextRegisterer() const
Instance suivante (nullptr si la dernière)
InstanceType * previousRegisterer() const
Instance précédente (nullptr si la première)
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.