Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AnyItemLinkFamily.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/* AnyItemLinkFamily.h (C) 2000-2012 */
9/* */
10/* Famille de liens entre any items. */
11/*---------------------------------------------------------------------------*/
12
13#ifndef ARCANE_ANYITEM_ANYITEMLINKFAMILY_H
14#define ARCANE_ANYITEM_ANYITEMLINKFAMILY_H
15
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19#include "arcane/anyitem/AnyItemGlobal.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24ARCANE_BEGIN_NAMESPACE
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29ANYITEM_BEGIN_NAMESPACE
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
37template<typename U, typename V>
38class PairT
39{
40public:
41 PairT(U u, V v) : m_u(u), m_v(v) {}
42 U m_u;
43 V m_v;
44};
45
46template<typename U, typename V>
47inline PairT<U,V> Pair(U u, V v) { return PairT<U,V>(u,v); }
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
68{
69public:
70
75 {
76 friend class LinkFamilyInternal;
77
78#ifdef ARCANE_ANYITEM_USEPACKEDDATA
79 public:
80 LinkData() : m_packed_data(0) {}
82 Integer groupIndex() const { return m_packed_data >> m_group_shift; }
84 Integer varIndex() const { return m_packed_data & m_integer_mask; }
86 Integer localId() const { return (m_packed_data >> m_local_id_shift) & m_integer_mask; }
88 bool operator==(const LinkData& data) const { return m_packed_data == data.m_packed_data; }
89private:
90 static const Integer m_integer_size = 26;
91 static const Int64 m_integer_mask = (Int64(1)<<m_integer_size)-1;
92 static const Integer m_short_size = 8;
93 static const Int64 m_short_mask = (Int64(1)<<m_short_size)-1;
94 static const Integer m_group_shift = 52;
95 static const Int64 m_group_mask = m_short_mask<<m_group_shift;
96 static const Integer m_local_id_shift = m_integer_size;
98
99 inline void setGroupIndex(Integer group_index) {
100 ARCANE_ASSERT(((group_index & ~m_short_mask) == 0),("Too large group index %d", group_index));
101 m_packed_data = (m_packed_data & ~m_group_mask) | (Int64(group_index)<<m_group_shift);
102 ARCANE_ASSERT((groupIndex() == group_index),("Corrupted data write detected"));
103 }
104 inline void setLocalId(Integer local_id) {
105 ARCANE_ASSERT(((local_id & ~m_integer_mask) == 0),("Too large local id %d", local_id));
107 ARCANE_ASSERT((localId() == local_id),("Corrupted data write detected"));
108 }
109 inline void setVarIndex(Integer item_local_id) {
110 ARCANE_ASSERT(((item_local_id & ~m_integer_mask) == 0),("Too large item local id %d", item_local_id));
112 ARCANE_ASSERT((varIndex() == item_local_id),("Corrupted data write detected"));
113 }
114 private:
115 Int64 m_packed_data;
116#else /* ARCANE_ANYITEM_USEPACKEDDATA */
117 public:
118 LinkData() : m_group_index(0), m_local_id(0), m_var_index(0) {}
120 Integer groupIndex() const { return m_group_index; }
122 Integer varIndex() const { return m_var_index; }
124 Integer localId() const { return m_local_id; }
126 bool operator==(const LinkData& data) const {
127 return m_group_index == data.m_group_index
128 && m_local_id == data.m_local_id
129 && m_var_index == data.m_var_index;
130 }
131 private:
132 inline void setGroupIndex(Integer group_index) { m_group_index = group_index; }
133 inline void setLocalId(Integer local_id) { m_local_id = local_id; }
134 inline void setVarIndex(Integer item_local_id) { m_var_index = item_local_id; }
135 private:
136 unsigned m_group_index;
137 unsigned m_local_id;
138 Integer m_var_index;
139#endif /* ARCANE_ANYITEM_USEPACKEDDATA */
140 };
141
147 {
148 public:
149 LinkIndex()
150 : m_index(0) {}
151 LinkIndex(Integer index)
152 : m_index(index) {}
153 inline Integer index() const { return m_index; }
154 protected:
155 Integer m_index;
156 };
157
162 : public LinkIndex
163 {
164 public:
167 : LinkIndex(), m_sources(sources), m_targets(targets) {}
168 Enumerator(const Enumerator& e)
169 : LinkIndex(), m_sources(e.m_sources), m_targets(e.m_targets) {}
170 inline bool hasNext() const { return m_sources.size() != m_index; }
171 inline void operator++() { m_index++; }
173 inline const LinkData& back() const {
174 return m_sources[m_index];
175 }
177 inline const LinkData& front() const {
178 return m_targets[m_index];
179 }
180 private:
185 };
186
190 class Link
191 : public LinkIndex
192 {
193 public:
194
198 template<typename U, typename V>
200 {
201 // Adder pour une pair de groupe
203 : m_family(family), m_a(a), m_b(b), m_used(false) {}
204 ~LinkAdder()
205 {
206 ARCANE_ASSERT((m_used == true),("LinkAdder never used"));
207 }
208
210 template<typename R, typename S>
211 inline void operator<<(const PairT<R,S>& p)
212 {
213 ARCANE_ASSERT((m_used == false),("VariableAdder already used"));
214 m_family.addSourceNode(p.m_u,m_a);
215 m_family.addTargetNode(p.m_v,m_b);
216 m_used = true;
217 }
218
219 private:
222
225
228
230 bool m_used;
231 };
232
233 public:
234
235 Link(LinkFamilyInternal& family, Integer index)
236 : LinkIndex(index), m_family(family), m_used(false) {}
237 ~Link()
238 {
239 ARCANE_ASSERT((m_used == true),("Link never used"));
240 }
241
243 template<typename U, typename V>
245 {
246 m_used = true;
247 return LinkAdder<U,V>(m_family,a,b);
248 }
249
250 private:
251
254
256 bool m_used;
257 };
258
259private:
260
261 typedef std::set<ILinkFamilyObserver*> LinkFamilyObservers;
262
263public:
264
266 LinkFamilyInternal(const Family& family)
267 : m_family(family)
268 , m_nb_link(0)
269 {
270 m_family.registerObserver(*this);
271 }
272
274 {
275 arcaneCallFunctionAndTerminateIfThrow([&]() { m_family.removeObserver(*this);});
276 }
277
279 inline Link newLink()
280 {
281 if(m_nb_link >= capacity()) {
282 m_source_nodes.reserve(2 * capacity());
283 m_target_nodes.reserve(2 * capacity());
284 _notifyFamilyIsReserved();
285 }
286 m_nb_link++;
287 m_source_nodes.resize(m_nb_link);
288 m_target_nodes.resize(m_nb_link);
289 return Link(*this,m_nb_link-1);
290 }
291
293 inline void reserve(Integer size) {
294 m_source_nodes.reserve(size);
295 m_target_nodes.reserve(size);
296 _notifyFamilyIsReserved();
297 }
298
300 inline Enumerator enumerator() const { return Enumerator(m_source_nodes, m_target_nodes); }
301
303 inline Integer capacity() const {
304 return m_source_nodes.capacity();
305 }
306
308 void clear() {
309 m_nb_link = 0;
310 m_source_nodes.clear();
311 m_target_nodes.clear();
312 _notifyFamilyIsInvalidate();
313 }
314
317 {
318 LinkFamilyObservers::const_iterator it = m_observers.find(&observer);
319 if(it != m_observers.end())
320 throw FatalErrorException("LinkFamilyObserver already registered");
321 m_observers.insert(&observer);
322 }
323
326 {
327 LinkFamilyObservers::const_iterator it = m_observers.find(&observer);
328 if(it == m_observers.end())
329 throw FatalErrorException("LinkFamilyObserver not registered");
330 m_observers.erase(it);
331 }
332
335 // Si la famille change, on invalide la famille des liaisons
336 clear();
337 _notifyFamilyIsInvalidate();
338 }
339
340 // Notifie que la famille est agrandie
342 // On ne fait rien dans ce cas
343 }
344
345public:
346
347 template<typename T, typename V>
348 inline void addSourceNode(const T& t, ItemGroupT<V> group) {
349 //_addNode(t, group, m_source_nodes);
350 initLinkData(m_source_nodes.back(), t, group);
351 }
352
353 template<typename T, typename V>
354 inline void addTargetNode(const T& t, ItemGroupT<V> group) {
355 //_addNode(t, group, m_target_nodes);
356 initLinkData(m_target_nodes.back(), t, group);
357 }
358
359 const LinkData& source(const LinkIndex& link) const {
360 return m_source_nodes[link.index()];
361 }
362
363 const LinkData& target(const LinkIndex& link) const {
364 return m_target_nodes[link.index()];
365 }
366
367public:
368
369 const Family& family() const {
370 return m_family;
371 }
372
373private:
374
375 // //! Ajout des noeuds des liaisons par type d'item
376 // // non optimal pour les variables partielles, il faut aller checher la
377 // // position de l'item dans le groupe
378 // template<typename T>
379 // inline void _addNode(const T& t, ItemGroupT<T> group, Arcane::Array<LinkData>& nodes) {
380 // LinkData& data = nodes.back();
381 // const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
382 // ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
383 // data.setGroupIndex(info->group_index);
384 // const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
385 // data.setLocalId(info->local_id_offset + local_index);
386 // if(info->is_partial) {
387 // const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
388 // data.setVarIndex(local_index);
389 // } else {
390 // data.setVarIndex(t.localId());
391 // }
392 // }
393
394 // //! Ajout des noeuds des liaisons par énumerateurs
395 // // optimal pour les variables partielles
396 // template<typename T>
397 // inline void _addNode(const ItemEnumeratorT<T>& t, ItemGroupT<T> group, Arcane::Array<LinkData>& nodes) {
398 // LinkData& data = nodes.back();
399 // const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
400 // ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
401 // data.setGroupIndex(info->group_index);
402 // const Integer local_index = t.index();
403 // data.setLocalId(info->local_id_offset + local_index);
404 // if(info->is_partial) {
405 // data.setVarIndex(local_index);
406 // } else {
407 // data.setVarIndex(t.localId());
408 // }
409 // }
410
411public:
412
414 // non optimal pour les variables partielles, il faut aller checher la
415 // position de l'item dans le groupe
416 template<typename T>
417 void initLinkData(LinkData& data, const T& t, ItemGroupT<T> group) const
418 {
419 const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
420 ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
421 data.setGroupIndex(info->group_index);
422 const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
423 data.setLocalId(info->local_id_offset + local_index);
424 if(info->is_partial) {
425 const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
426 data.setVarIndex(local_index);
427 } else {
428 data.setVarIndex(t.localId());
429 }
430 }
431
433 // optimal pour les variables partielles
434 template<typename T>
435 void initLinkData(LinkData& data, const ItemEnumeratorT<T>& t, ItemGroupT<T> group) const
436 {
437 const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
438 ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
439 data.setGroupIndex(info->group_index);
440 const Integer local_index = t.index();
441 data.setLocalId(info->local_id_offset + local_index);
442 if(info->is_partial) {
443 data.setVarIndex(local_index);
444 } else {
445 data.setVarIndex(t.localId());
446 }
447 }
448
450 Item item(const LinkData& link_data) const {
451 return m_family.item(link_data);
452 }
453
454private:
455
456 void _notifyFamilyIsInvalidate() {
457 for(LinkFamilyObservers::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
458 (*it)->notifyFamilyIsInvalidate();
459 }
460
461 void _notifyFamilyIsReserved() {
462 for(LinkFamilyObservers::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
463 (*it)->notifyFamilyIsReserved();
464 }
465
466private:
467
469 const Family m_family;
470
473
476
478 Integer m_nb_link;
479
481 // Pour que les objets construits sur la famille ne puissent pas la modifier
482 mutable LinkFamilyObservers m_observers;
483};
484
485/*---------------------------------------------------------------------------*/
486/*---------------------------------------------------------------------------*/
487
492 : public IFamilyObserver
493{
494public:
495
500
501public:
502
503 LinkFamily(const Family& f)
504 : m_internal(new LinkFamilyInternal(f)) {}
505
506 LinkFamily(const LinkFamily& f)
507 : m_internal(f.m_internal) {}
508
509 ~LinkFamily() {}
510
512 inline Link newLink()
513 {
514 return m_internal->newLink();
515 }
516
518 inline void reserve(Integer size) {
519 m_internal->reserve(size);
520 }
521
523 inline Enumerator enumerator() const { return m_internal->enumerator(); }
524
526 inline Integer capacity() const {
527 return m_internal->capacity();
528 }
529
531 void clear() {
532 m_internal->clear();
533 }
534
537 {
538 m_internal->registerObserver(observer);
539 }
540
543 {
544 m_internal->removeObserver(observer);
545 }
546
549 m_internal->notifyFamilyIsInvalidate();
550 }
551
554 m_internal->notifyFamilyIsIncreased();
555 }
556
557public:
558
559 template<typename T, typename V>
560 inline void addSourceNode(const T& t, ItemGroupT<V> group) {
561 m_internal->addSourceNode(t,group);
562 }
563
564 template<typename T, typename V>
565 inline void addTargetNode(const T& t, ItemGroupT<V> group) {
566 m_internal->addTargetNode(t,group);
567 }
568
569public:
570
571 LinkFamilyInternal * internal() const {
572 return m_internal.get();
573 }
574
575private:
576
579};
580
581/*---------------------------------------------------------------------------*/
582/*---------------------------------------------------------------------------*/
583
584ANYITEM_END_NAMESPACE
585ARCANE_END_NAMESPACE
586
587/*---------------------------------------------------------------------------*/
588/*---------------------------------------------------------------------------*/
589
590#endif /* ARCANE_ANYITEM_ANYITEMLINKFAMILY_H */
Interface d'observeurs de famille AnyItem.
Interface d'observeurs de famille de liaisons AnyItem.
Classe de base d'un élément de maillage.
Definition Item.h:83
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
const Arcane::Array< LinkData > & m_sources
Toutes les données back.
const LinkData & back() const
Données du lien back.
const Arcane::Array< LinkData > & m_targets
Toutes les données front.
const LinkData & front() const
Données du lien front.
unsigned m_group_index
Index du groupe d'où vient cet item.
Integer m_var_index
Index pour les partiels, localId sinon.
bool operator==(const LinkData &data) const
Opérateur de comparaison.
unsigned m_local_id
Identifiant dans l(indexation globale de AnyItem::Family.
Integer varIndex() const
Identifiant localId de l'item référencé dans sa famille IItemFamily d'origine.
Integer localId() const
Identifiant localId de l'item référencé dans sa famille AnyItemFamily.
Integer groupIndex() const
Identifiant du groupe auquel est associé l'item référencé par ce LinkData.
Famille de liens AnyItem partie interne les données stockées sont les localid des items et l'offset d...
void initLinkData(LinkData &data, const ItemEnumeratorT< T > &t, ItemGroupT< T > group) const
Ajout des noeuds des liaisons par énumerateurs.
LinkFamilyInternal(const Family &family)
Famille de liens pour une famille anyitem.
Link newLink()
Création d'un nouveau lien vide.
LinkFamilyObservers m_observers
Observeurs de la famille.
Integer m_nb_link
Nombre de liens.
Arcane::UniqueArray< LinkData > m_source_nodes
Données back.
Enumerator enumerator() const
Enumérateurs des liens.
void clear()
Vide la famille.
void notifyFamilyIsInvalidate()
Notifie que la famille est invalidée.
void removeObserver(ILinkFamilyObserver &observer) const
Détruit un observeur de la famille.
Integer capacity() const
retourne la capacité
void registerObserver(ILinkFamilyObserver &observer) const
Enrgistre un observeur de la famille.
Item item(const LinkData &link_data) const
Retoune l'item concret associé à ce AnyItem.
void initLinkData(LinkData &data, const T &t, ItemGroupT< T > group) const
Ajout des noeuds des liaisons par type d'item.
void reserve(Integer size)
Réserve une capacité de liens.
Arcane::UniqueArray< LinkData > m_target_nodes
Données front.
const Family m_family
Famille AnyItem.
void notifyFamilyIsIncreased()
Notifie à l'observeur que la famille est agrandie.
Famille de liens AnyItem (pattern flyweight)
Integer capacity() const
retourne la capacité
void reserve(Integer size)
Réserve une capacité de liens.
Enumerator enumerator() const
Enumérateurs des liens.
void notifyFamilyIsIncreased()
Notifie que la famille est agrandie.
void registerObserver(ILinkFamilyObserver &observer) const
Enrgistre un observeur de la famille.
SharedPtrT< LinkFamilyInternal > m_internal
Famille de liens interne.
void removeObserver(ILinkFamilyObserver &observer) const
Detruit un observeur de la famille.
void clear()
Vide la famille.
void notifyFamilyIsInvalidate()
Notifie que la famille est invalidée.
Link newLink()
Création d'un nouveau lien vide.
Outil pour créer une pair d'items.
Exception lorsqu'une erreur fatale est survenue.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)