Arcane  v3.14.10.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-2024 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-2024 */
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
41ExternalReferenceCounterAccessor<T>::
42addReference(T* t)
43{
44 if constexpr (impl::HasInternalAddReference<T>::value)
45 t->_internalAddReference();
46 else
47 t->addReference();
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53template <class T> ARCCORE_EXPORT void
54ExternalReferenceCounterAccessor<T>::
55removeReference(T* t)
56{
57 if constexpr (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 * \brief Implémentation thread-safe d'un compteur de référence.
70 *
71 * L'implémentation utilise un std::atomic pour conserver le nombre de
72 * références.
73 *
74 * La méthode removeReference() détruit l'instance lorsque ce compteur
75 * de référence atteint 0.
76 *
77 * Cette classe est interne à Arcane.
78 */
79class ARCCORE_BASE_EXPORT ReferenceCounterImpl
80{
81 template <typename InstanceType> friend class impl::ReferenceCounterWrapper;
82
83 public:
84
85 virtual ~ReferenceCounterImpl() = default;
86
87 public:
88
89 // TODO: Rendre obsolète
90 void addReference()
91 {
92 ++m_nb_ref;
93 }
94
95 // TODO: Rendre obsolète
96 void removeReference()
97 {
98 // Décrémente et retourne la valeur d'avant.
99 // Si elle vaut 1, cela signifie qu'on n'a plus de références
100 // sur l'objet et qu'il faut le détruire.
101 Int32 v = std::atomic_fetch_add(&m_nb_ref, -1);
102 if (v == 1) {
103 if (_destroyThisReference())
104 delete this;
105 }
106 }
107
108 public:
109
110 void _internalAddReference()
111 {
112 ++m_nb_ref;
113 }
114 bool _internalRemoveReference()
115 {
116 // Décrémente et retourne la valeur d'avant.
117 // Si elle vaut 1, cela signifie qu'on n'a plus de références
118 // sur l'objet et qu'il faut éventuellement le détruire.
119 Int32 v = std::atomic_fetch_add(&m_nb_ref, -1);
120 if (v == 1)
121 return _destroyThisReference();
122 return false;
123 }
124
125 private:
126
127 // Méthodes accessibles uniquement depuis ReferenceCounterWrapper
128 void _setExternalDeleter(RefBase::DeleterBase* v)
129 {
130 delete m_external_deleter;
131 m_external_deleter = v;
132 }
133 RefBase::DeleterBase* _externalDeleter() const
134 {
135 return m_external_deleter;
136 }
137
138 private:
139
140 std::atomic<Int32> m_nb_ref = 0;
141 RefBase::DeleterBase* m_external_deleter = nullptr;
142
143 private:
144
145 //! Retourne \a true si l'instance doit être détruite par l'appel à operator delete()
146 bool _destroyThisReference()
147 {
148 if (!m_external_deleter)
149 return true;
150 bool do_delete = false;
151 if (!m_external_deleter->m_no_destroy) {
152 bool is_destroyed = m_external_deleter->_destroyHandle(this, m_external_deleter->m_handle);
153 if (!is_destroyed) {
154 do_delete = true;
155 }
156 }
157 delete m_external_deleter;
158 m_external_deleter = nullptr;
159 return do_delete;
160 }
161};
162
163/*---------------------------------------------------------------------------*/
164/*---------------------------------------------------------------------------*/
165/*!
166 * \internal
167 * Macro générique pour définir les méthodes gérant les compteurs de référence.
168 */
169#define ARCCORE_INTERNAL_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS(OPTIONAL_OVERRIDE) \
170 private: \
171\
172 using BaseCounterType = ::Arccore::ReferenceCounterImpl; \
173\
174 public: \
175\
176 BaseCounterType* _internalReferenceCounter() OPTIONAL_OVERRIDE \
177 { \
178 return this; \
179 } \
180 void _internalAddReference() OPTIONAL_OVERRIDE \
181 { \
182 BaseCounterType::_internalAddReference(); \
183 } \
184 bool _internalRemoveReference() OPTIONAL_OVERRIDE \
185 { \
186 return BaseCounterType::_internalRemoveReference(); \
187 }
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191/*!
192 * \brief Macro pour définir les méthodes gérant les compteurs
193 * de référence.
194 *
195 * Cette macro s'utilise dans une classe implémentant une interface
196 * pour laquelle la macro ARCCORE_DECLARE_REFERENCE_COUNTED_INCLASS_METHODS()
197 * a été utilisée. La classe implémentation doit dériver de
198 * ReferenceCounterImpl. Par exemple:
199 *
200 * \code
201 * class MyClass
202 * : public ReferenceCounterImpl
203 * , public IMyInterface
204 * {
205 * ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS();
206 * public:
207 * void myMethod1() override;
208 * };
209 * \endcode
210 */
211#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS() \
212 ARCCORE_INTERNAL_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS(override)
213
214/*---------------------------------------------------------------------------*/
215/*---------------------------------------------------------------------------*/
216
217/*!
218 * \brief Macro pour définir les méthodes et types une classe qui
219 * utilise un compteur de référence.
220 *
221 * Cette macro doit être utilisée pour une classe pour laquelle on
222 * a utilisé la macro ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(). Elle doit
223 * se trouver dans une seule unité de translation (un fichier '.cc' par
224 * exemple) et être utilisée dans le namespace Arccore. Par exemple:
225 *
226 * \code
227 * namespace Arccore
228 * {
229 * ARCCORE_DEFINE_REFERENCE_COUNTED_CLASS(MyNamespace::MyClass);
230 * }
231 * \endcode
232 */
233#define ARCCORE_DEFINE_REFERENCE_COUNTED_CLASS(class_name) \
234 template class ExternalReferenceCounterAccessor<class_name>
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
239} // End namespace Arccore
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
244#endif
bool m_no_destroy
Indique si on doit appeler le destructeur de l'instance lorsqu'il n'y a plus de références dessus.
Definition RefBase.h:80
Internal::ExternalRef m_handle
Handle externe qui se charge de la destruction de l'instance.
Definition RefBase.h:75
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.
Espace de nom de Arccore.
Definition ArcaneTypes.h:24
std::int32_t Int32
Type entier signé sur 32 bits.