Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
Event.cc
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/* Event.cc (C) 2000-2023 */
9/* */
10/* Gestionnaires d'évènements. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Event.h"
15#include "arcane/utils/UniqueArray.h"
16#include "arcane/utils/FatalErrorException.h"
17
18#include <set>
19#include <iostream>
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23/*!
24 * \file utils/Event.h
25 *
26 * \brief Fichier contenant les mécanismes de gestion des évènements.
27 */
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
38{
39 public:
40 Impl(){}
41 public:
42 void rebuildOberversArray()
43 {
44 m_observers_array.clear();
45 m_observers_array.reserve(arcaneCheckArraySize(m_observers.size()));
46 for( auto o : m_observers )
47 m_observers_array.add(o);
48 }
49 public:
50 std::set<EventObserverBase*> m_auto_destroy_observers;
51 std::set<EventObserverBase*> m_observers;
52 UniqueArray<EventObserverBase*> m_observers_array;
53};
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
58EventObservableBase::
59EventObservableBase()
60: m_p(new Impl())
61{
62}
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67EventObservableBase::
68~EventObservableBase()
69{
70 try{
71 detachAllObservers();
72 }
73 catch(...){
74 std::cerr << "ERROR: Exception launched during call to ~EventObservableBase().\n";
75 }
76 delete m_p;
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
82void EventObservableBase::
83_attachObserver(EventObserverBase* obs,bool is_auto_destroy)
84{
85 // Vérifie que l'observeur n'est pas dans la liste.
86 if (m_p->m_observers.find(obs)!=m_p->m_observers.end())
87 ARCANE_FATAL("Observer is already attached to this observable");
88 obs->_notifyAttach(this);
89 m_p->m_observers.insert(obs);
90 m_p->rebuildOberversArray();
91 if (is_auto_destroy)
92 m_p->m_auto_destroy_observers.insert(obs);
93}
94
95/*---------------------------------------------------------------------------*/
96/*---------------------------------------------------------------------------*/
97
98void EventObservableBase::
99_detachObserver(EventObserverBase* obs)
100{
101 // NOTE: il est impossible de détacher un observeur qui a été alloué
102 // dynamiquement. Il n'y a donc pas besoin de mettre à jour
103 // m_p->m_auto_destroy_observers.
104 bool is_ok = false;
105 for( auto o : m_p->m_observers )
106 if (o==obs){
107 m_p->m_observers.erase(o);
108 is_ok = true;
109 break;
110 }
111
112 // Lance une exception si pas trouvé
113 if (!is_ok)
114 ARCANE_FATAL("observer is not registered to this observable");
115 obs->_notifyDetach();
116 m_p->rebuildOberversArray();
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122ConstArrayView<EventObserverBase*> EventObservableBase::
123_observers() const
124{
125 return m_p->m_observers_array;
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
131void EventObservableBase::
132detachAllObservers()
133{
134 for( auto o : m_p->m_observers )
135 o->_notifyDetach();
136 m_p->m_observers.clear();
137 for( auto o : m_p->m_auto_destroy_observers )
138 delete o;
139}
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143
144bool EventObservableBase::
145hasObservers() const
146{
147 return (m_p->m_observers.size()!=0);
148}
149
150
151/*---------------------------------------------------------------------------*/
152/*---------------------------------------------------------------------------*/
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157EventObserverBase::
158~EventObserverBase() ARCANE_NOEXCEPT_FALSE
159{
160 if (m_observable)
161 m_observable->_detachObserver(this);
162}
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
167void EventObserverBase::
168_notifyDetach()
169{
170 if (!m_observable)
171 ARCANE_FATAL("EventObserver is not attached to an EventObservable");
172 m_observable = nullptr;
173}
174
175/*---------------------------------------------------------------------------*/
176/*---------------------------------------------------------------------------*/
177
178void EventObserverBase::
179_notifyAttach(EventObservableBase* obs)
180{
181 if (m_observable)
182 ARCANE_FATAL("EventObserver is already attached to an EventObservable");
183 m_observable = obs;
184}
185
186/*---------------------------------------------------------------------------*/
187/*---------------------------------------------------------------------------*/
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
192EventObserverPool::
193~EventObserverPool()
194{
195 clear();
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
202clear()
203{
204 for( auto o : m_observers )
205 delete o;
206 m_observers.clear();
207}
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211
214{
215 m_observers.add(obs);
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
223
224namespace
225{
226class TestMemberCall
227{
228 public:
229 void my_func(int a,int b)
230 {
231 std::cout << "THIS_IS_MY FUNC XA=" << a << " B=" << b << '\n';
232 }
233 void operator()(int a,int b)
234 {
235 std::cout << "THIS_IS OPERATOR() FUNC XA=" << a << " B=" << b << '\n';
236 }
237};
238}
239extern "C++" ARCANE_UTILS_EXPORT void
240 _internalTestEvent()
241{
242 using std::placeholders::_1;
243 using std::placeholders::_2;
244
245 int f = 3;
246 auto func = [&](int a,int b){
247 std::cout << "XA=" << a << " B=" << b << " f=" << f << '\n';
248 f = a+b;
249 };
250 auto func2 = [&](int a,int b){
251 std::cout << "FUNC2: XA=" << a << " B=" << b << " f=" << f << '\n';
252 };
253 TestMemberCall tmc;
254 EventObserver<int,int> x2(func);
255 {
256 EventObservable<int,int> xevent;
257 EventObserverPool pool;
258 {
259 EventObserver<int,int> xobserver;
260 // NOTE: le test suivnant ne marche pas avec MSVS2013
261 //std::function<void(TestMemberCall*,int,int)> kk1(&TestMemberCall::my_func);
262 std::function<void(int,int)> kk( std::bind( &TestMemberCall::my_func, tmc, _1, _2 ) );
263 //std::function<void(int,int)> kk2( std::bind( &TestMemberCall::my_func, tmc ) );
264 //auto kk( std::bind( &TestMemberCall::my_func, &tmc ) );
265 EventObserver<int,int> x4(kk);
266 EventObserver<int,int> x3(tmc);
267 xevent.attach(&x2);
268 xevent.attach(&x3);
269 xevent.attach(&x4);
270 xevent.attach(&xobserver);
271 xevent.notify(2,3);
272 xevent.detach(&x4);
273 }
274 xevent.attach(pool,func2);
275 }
276 std::cout << "(After) F=" << f << '\n';
277 if (f!=5)
278 ARCANE_FATAL("Bad value for f");
279 {
280 EventObserver<int,int>* eo1 = nullptr;
281 EventObservable<int,int> xevent;
282 {
283 eo1 = new EventObserver<int,int>( std::bind( &TestMemberCall::my_func, tmc, _1, _2 ) );
284 xevent.attach(eo1);
285 }
286 xevent.notify(2,4);
287 delete eo1;
288 }
289}
290
291/*---------------------------------------------------------------------------*/
292/*---------------------------------------------------------------------------*/
293
294} // End namespace Arcane
295
296/*---------------------------------------------------------------------------*/
297/*---------------------------------------------------------------------------*/
298
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fichier contenant les mécanismes de gestion des évènements.
void clear()
Supprime tous les observateurs associés à cette instance.
Definition Event.cc:202
void add(EventObserverBase *x)
Ajoute l'observateur x.
Definition Event.cc:213
Vecteur 1D de données avec sémantique par valeur (style STL).
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....