Arcane  v3.16.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ReferenceCounterImpl.h
Aller à la documentation de ce fichier.
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* ReferenceCounterImpl.h (C) 2000-2025 */
9/* */
10/* Implémentations liées au gestionnaire de compteur de référence. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_BASE_REFERENCECOUNTERIMPL_H
13#define ARCCORE_BASE_REFERENCECOUNTERIMPL_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arccore/base/ReferenceCounter.h"
18#include "arccore/base/RefBase.h"
19
20#include <atomic>
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24/*!
25 * \file ReferenceCounterImpl.h
26 *
27 * Ce fichier ne doit être inclus que par les classes implémentations
28 * utilisant un compte de référence. Pour les déclarations, il faut utiliser
29 * le fichier 'RefDeclarations.h'
30 */
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arccore
35{
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40template <class T> ARCCORE_EXPORT void
42addReference(T* t)
43{
44 if constexpr (::Arcane::impl::HasInternalAddReference<T>::value)
45 t->_internalAddReference();
46 else
47 t->addReference();
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53template <class T> ARCCORE_EXPORT void
56{
57 if constexpr (::Arcane::impl::HasInternalRemoveReference<T>::value) {
58 bool need_destroy = t->_internalRemoveReference();
59 if (need_destroy)
60 delete t;
61 }
62 else
63 t->removeReference();
64}
65
66/*---------------------------------------------------------------------------*/
67/*---------------------------------------------------------------------------*/
68
69} // namespace Arccore
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
74namespace Arcane
75{
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79/*!
80 * \brief Implémentation thread-safe d'un compteur de référence.
81 *
82 * L'implémentation utilise un std::atomic pour conserver le nombre de
83 * références.
84 *
85 * La méthode removeReference() détruit l'instance lorsque ce compteur
86 * de référence atteint 0.
87 *
88 * Cette classe est interne à Arcane.
89 */
90class ARCCORE_BASE_EXPORT ReferenceCounterImpl
91{
92 template <typename InstanceType> friend class impl::ReferenceCounterWrapper;
93
94 public:
95
96 virtual ~ReferenceCounterImpl() = default;
97
98 public:
99
100 // TODO: Rendre obsolète
101 void addReference()
102 {
103 ++m_nb_ref;
104 }
105
106 // TODO: Rendre obsolète
107 void removeReference()
108 {
109 // Décrémente et retourne la valeur d'avant.
110 // Si elle vaut 1, cela signifie qu'on n'a plus de références
111 // sur l'objet et qu'il faut le détruire.
112 Int32 v = std::atomic_fetch_add(&m_nb_ref, -1);
113 if (v == 1) {
114 if (_destroyThisReference())
115 delete this;
116 }
117 }
118
119 public:
120
121 void _internalAddReference()
122 {
123 ++m_nb_ref;
124 }
125 bool _internalRemoveReference()
126 {
127 // Décrémente et retourne la valeur d'avant.
128 // Si elle vaut 1, cela signifie qu'on n'a plus de références
129 // sur l'objet et qu'il faut éventuellement le détruire.
130 Int32 v = std::atomic_fetch_add(&m_nb_ref, -1);
131 if (v == 1)
132 return _destroyThisReference();
133 return false;
134 }
135
136 private:
137
138 // Méthodes accessibles uniquement depuis ReferenceCounterWrapper
139 void _setExternalDeleter(RefBase::DeleterBase* v)
140 {
141 delete m_external_deleter;
142 m_external_deleter = v;
143 }
144 RefBase::DeleterBase* _externalDeleter() const
145 {
146 return m_external_deleter;
147 }
148
149 private:
150
151 std::atomic<Int32> m_nb_ref = 0;
152 RefBase::DeleterBase* m_external_deleter = nullptr;
153
154 private:
155
156 //! Retourne \a true si l'instance doit être détruite par l'appel à operator delete()
157 bool _destroyThisReference()
158 {
159 if (!m_external_deleter)
160 return true;
161 bool do_delete = false;
162 if (!m_external_deleter->m_no_destroy) {
163 bool is_destroyed = m_external_deleter->_destroyHandle(this, m_external_deleter->m_handle);
164 if (!is_destroyed) {
165 do_delete = true;
166 }
167 }
168 delete m_external_deleter;
169 m_external_deleter = nullptr;
170 return do_delete;
171 }
172};
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176/*!
177 * \internal
178 * Macro générique pour définir les méthodes gérant les compteurs de référence.
179 */
180#define ARCCORE_INTERNAL_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS(OPTIONAL_OVERRIDE) \
181 private: \
182\
183 using BaseCounterType = ::Arcane::ReferenceCounterImpl; \
184\
185 public: \
186\
187 BaseCounterType* _internalReferenceCounter() OPTIONAL_OVERRIDE \
188 { \
189 return this; \
190 } \
191 void _internalAddReference() OPTIONAL_OVERRIDE \
192 { \
193 BaseCounterType::_internalAddReference(); \
194 } \
195 bool _internalRemoveReference() OPTIONAL_OVERRIDE \
196 { \
197 return BaseCounterType::_internalRemoveReference(); \
198 }
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202/*!
203 * \brief Macro pour définir les méthodes gérant les compteurs
204 * de référence.
205 *
206 * Cette macro s'utilise dans une classe implémentant une interface
207 * pour laquelle la macro ARCCORE_DECLARE_REFERENCE_COUNTED_INCLASS_METHODS()
208 * a été utilisée. La classe implémentation doit dériver de
209 * ReferenceCounterImpl. Par exemple:
210 *
211 * \code
212 * class MyClass
213 * : public ReferenceCounterImpl
214 * , public IMyInterface
215 * {
216 * ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS();
217 * public:
218 * void myMethod1() override;
219 * };
220 * \endcode
221 */
222#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS() \
223 ARCCORE_INTERNAL_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS(override)
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228/*!
229 * \brief Macro pour définir les méthodes et types une classe qui
230 * utilise un compteur de référence.
231 *
232 * Cette macro doit être utilisée pour une classe pour laquelle on
233 * a utilisé la macro ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(). Elle doit
234 * se trouver dans une seule unité de translation (un fichier '.cc' par
235 * exemple) et être utilisée dans le namespace Arccore. Par exemple:
236 *
237 * \code
238 * namespace Arccore
239 * {
240 * ARCCORE_DEFINE_REFERENCE_COUNTED_CLASS(MyNamespace::MyClass);
241 * }
242 * \endcode
243 */
244#define ARCCORE_DEFINE_REFERENCE_COUNTED_CLASS(class_name) \
245 template class ExternalReferenceCounterAccessor<class_name>
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250} // End namespace Arccore
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255#endif
Implémentation thread-safe d'un compteur de référence.
Wrapper autour d'une classe gérant son propre compteur de référence.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int32_t Int32
Type entier signé sur 32 bits.
Espace de nom de Arccore.