Arcane  v4.1.7.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
AbstractArray.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* AbstractArray.h (C) 2000-2026 */
9/* */
10/* Classe de base des tableaux. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_COMMON_ABSTRACTARRAY_H
13#define ARCCORE_COMMON_ABSTRACTARRAY_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arccore/base/Span.h"
18
19#include "arccore/common/ArrayTraits.h"
20#include "arccore/common/ArrayMetaData.h"
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Arcane
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30/*!
31 * \brief Classe de base interne pour les tableaux.
32 *
33 * Cette classe gère uniquement les meta-données pour les tableaux comme
34 * le nombre d'éléments ou la capacité.
35 *
36 * \a m_md est un pointeur contenant les meta-donné du tableau. Si le
37 * tableau est partagé (SharedArray, SharedArray2), alors ce pointeur
38 * est alloué dynamiquement et dans ce cas _isUseOwnMetaData() doit
39 * retourner \a false. Si le tableau n'est pas partagé (UniqueArray ou
40 * UniqueArray2), alors les meta-données sont conservées directement
41 * dans l'instance du tableau pour éviter des allocations inutiles
42 * et \a m_md pointe alors vers \a m_meta_data. Dans tous les cas, il
43 * ne faut pas utiliser \a m_meta_data directement, mais toujours passer
44 * par \a m_md.
45 */
46class ARCCORE_COMMON_EXPORT AbstractArrayBase
47{
48 public:
49
50 AbstractArrayBase()
51 {
52 m_md = &m_meta_data;
53 }
54 virtual ~AbstractArrayBase() = default;
55
56 public:
58 IMemoryAllocator* allocator() const
59 {
60 return m_md->allocation_options.allocator();
61 }
62 MemoryAllocationOptions allocationOptions() const
63 {
64 return m_md->allocation_options;
65 }
66 /*!
67 * \brief Positionne le nom du tableau pour les informations de debug.
68 *
69 * Ce nom peut être utilisé par exemple pour les affichages listing.
70 */
71 void setDebugName(const String& name);
72 //! Nom de debug (nul si aucun nom spécifié)
73 String debugName() const;
74
75 protected:
76
77 ArrayMetaData* m_md = nullptr;
78 ArrayMetaData m_meta_data;
79
80 protected:
81
82 //! Méthode explicite pour une RunQueue nulle.
83 static constexpr RunQueue* _nullRunQueue() { return nullptr; }
84
85 /*!
86 * \brief Indique si \a m_md fait référence à \a m_meta_data.
87 *
88 * C'est le cas pour les UniqueArray et UniqueArray2 mais
89 * pas pour les SharedArray et SharedArray2.
90 */
91 virtual bool _isUseOwnMetaData() const
92 {
93 return true;
94 }
95
96 protected:
97
98 void _swapMetaData(AbstractArrayBase& rhs)
99 {
100 std::swap(m_md, rhs.m_md);
101 std::swap(m_meta_data, rhs.m_meta_data);
102 _checkSetUseOwnMetaData();
103 rhs._checkSetUseOwnMetaData();
104 }
105
106 void _copyMetaData(const AbstractArrayBase& rhs)
107 {
108 // Déplace les meta-données
109 // Attention si on utilise m_meta_data alors il
110 // faut positionner m_md pour qu'il pointe vers notre propre m_meta_data.
111 m_meta_data = rhs.m_meta_data;
112 m_md = rhs.m_md;
113 _checkSetUseOwnMetaData();
114 }
115
116 void _allocateMetaData()
117 {
118#ifdef ARCCORE_CHECK
119 if (m_md->is_not_null)
120 ArrayMetaData::throwNullExpected();
121#endif
122 if (_isUseOwnMetaData()) {
123 m_meta_data = ArrayMetaData();
124 m_md = &m_meta_data;
125 }
126 else {
127 m_md = new ArrayMetaData();
128 m_md->is_allocated_by_new = true;
129 }
130 m_md->is_not_null = true;
131 }
132
133 void _deallocateMetaData(ArrayMetaData* md)
134 {
135 if (md->is_allocated_by_new)
136 delete md;
137 else
138 *md = ArrayMetaData();
139 }
140
141 void _checkValidSharedArray()
142 {
143#ifdef ARCCORE_CHECK
144 if (m_md->is_not_null && !m_md->is_allocated_by_new)
145 ArrayMetaData::throwInvalidMetaDataForSharedArray();
146#endif
147 }
148
149 private:
150
151 void _checkSetUseOwnMetaData()
152 {
153 if (!m_md->is_allocated_by_new)
154 m_md = &m_meta_data;
155 }
156};
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160/*!
161 * \ingroup Collection
162 * \brief Classe abstraite de base d'un vecteur.
163 *
164 * Cette classe ne peut pas être utilisée directement. Pour utiliser un
165 * vecteur, choisissez la classe SharedArray ou UniqueArray.
166 */
167template <typename T>
169: public AbstractArrayBase
170{
171 public:
172
173 typedef typename ArrayTraits<T>::ConstReferenceType ConstReferenceType;
174 typedef typename ArrayTraits<T>::IsPODType IsPODType;
175 typedef AbstractArray<T> ThatClassType;
176 using TrueImpl = T;
177
178 public:
179
180 //! Type des éléments du tableau
181 typedef T value_type;
182 //! Type pointeur d'un élément du tableau
184 //! Type pointeur constant d'un élément du tableau
185 typedef const value_type* const_pointer;
186 //! Type de l'itérateur sur un élément du tableau
188 //! Type de l'itérateur constant sur un élément du tableau
190 //! Type référence d'un élément du tableau
192 //! Type référence constante d'un élément du tableau
193 typedef ConstReferenceType const_reference;
194 //! Type indexant le tableau
196 //! Type d'une distance entre itérateur éléments du tableau
197 typedef ptrdiff_t difference_type;
198
199 typedef std::reverse_iterator<iterator> reverse_iterator;
200 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
201
202 protected:
203
204 //! Construit un vecteur vide avec l'allocateur par défaut
206 {
207 }
208 //! Constructeur par déplacement. Ne doit être utilisé que par UniqueArray
209 AbstractArray(ThatClassType&& rhs) ARCCORE_NOEXCEPT
210 : m_ptr(rhs.m_ptr)
211 {
212 _copyMetaData(rhs);
213 rhs._reset();
214 }
215
216 ~AbstractArray() override
217 {
218 --m_md->nb_ref;
220 }
221
222 public:
223
224 AbstractArray(const AbstractArray<T>& rhs) = delete;
225 AbstractArray<T>& operator=(const AbstractArray<T>& rhs) = delete;
226
227 protected:
228
229 static constexpr Int64 typeSize() { return static_cast<Int64>(sizeof(T)); }
230 AllocatedMemoryInfo _currentMemoryInfo() const
231 {
232 return AllocatedMemoryInfo(m_ptr, m_md->size * typeSize(), m_md->capacity * typeSize());
233 }
234
235 protected:
236
237 /*!
238 * \brief Initialise le tableau avec la vue \a view.
239 *
240 * Cette méthode ne doit être appelée que dans un constructeur de la classe dérivée.
241 */
242 void _initFromSpan(const Span<const T>& view)
243 {
244 Int64 asize = view.size();
245 if (asize != 0) {
246 _internalAllocate(asize, _nullRunQueue());
247 _createRange(0, asize, view.data());
248 m_md->size = asize;
249 }
250 }
251
252 /*!
253 * \brief Construit un vecteur vide avec un allocateur spécifique \a a.
254 *
255 * Si \a acapacity n'est pas nul, la mémoire est allouée pour
256 * contenir \a acapacity éléments (mais le tableau reste vide).
257 *
258 * Cette méthode ne doit être appelée que dans un constructeur de la classe dérivée
259 * et uniquement par les classes utilisant une sémantique à la UniqueArray.
260 */
262 void* pre_allocated_buffer = nullptr)
263 {
264 _directFirstAllocateWithAllocator(acapacity, o, pre_allocated_buffer);
265 }
266
267 public:
268
269 //! Libère la mémoire utilisée par le tableau.
270 void dispose()
271 {
272 _destroy();
273 MemoryAllocationOptions options(m_md->allocation_options);
274 _internalDeallocate();
275 _setToSharedNull();
276 // Si on a un allocateur spécifique, il faut allouer un
277 // bloc pour conserver cette information.
278 if (options.allocator() != m_md->_allocator())
279 _directFirstAllocateWithAllocator(0, options);
281 }
282
283 public:
284
285 operator ConstArrayView<T>() const
286 {
287 return ConstArrayView<T>(ARCCORE_CAST_SMALL_SIZE(size()), m_ptr);
288 }
289 operator Span<const T>() const
290 {
291 return Span<const T>(m_ptr, m_md->size);
292 }
293 operator SmallSpan<const T>() const
294 {
295 return SmallSpan<const T>(m_ptr, ARCCORE_CAST_SMALL_SIZE(size()));
296 }
297
298 public:
299
300 //! Nombre d'éléments du vecteur
301 Integer size() const { return ARCCORE_CAST_SMALL_SIZE(m_md->size); }
302 //! Nombre d'éléments du vecteur
303 Integer length() const { return ARCCORE_CAST_SMALL_SIZE(m_md->size); }
304 //! Capacité (nombre d'éléments alloués) du vecteur
305 Integer capacity() const { return ARCCORE_CAST_SMALL_SIZE(m_md->capacity); }
306 //! Nombre d'éléments du vecteur (en 64 bits)
307 Int64 largeSize() const { return m_md->size; }
308 //! Nombre d'éléments du vecteur (en 64 bits)
309 Int64 largeLength() const { return m_md->size; }
310 //! Capacité (nombre d'éléments alloués) du vecteur (en 64 bits)
311 Int64 largeCapacity() const { return m_md->capacity; }
312 //! Capacité (nombre d'éléments alloués) du vecteur
313 bool empty() const { return m_md->size == 0; }
314 //! Vrai si le tableau contient l'élément de valeur \a v
315 bool contains(ConstReferenceType v) const
316 {
317 const T* ptr = m_ptr;
318 for (Int64 i = 0, n = m_md->size; i < n; ++i) {
319 if (ptr[i] == v)
320 return true;
321 }
322 return false;
323 }
324
325 public:
326
327 //! Elément d'indice \a i
328 ConstReferenceType operator[](Int64 i) const
329 {
330 ARCCORE_CHECK_AT(i, m_md->size);
331 return m_ptr[i];
332 }
333 //! Elément d'indice \a i
334 ConstReferenceType operator()(Int64 i) const
335 {
336 ARCCORE_CHECK_AT(i, m_md->size);
337 return m_ptr[i];
338 }
339
340 public:
341
342 //! Modifie les informations sur la localisation mémoire
344 {
345 m_md->_setMemoryLocationHint(new_hint, m_ptr, sizeof(T));
346 }
347
348 /*!
349 * \brief Positionne l'emplacement physique de la zone mémoire.
350 *
351 * \warning L'appelant doit garantir la cohérence entre l'allocateur
352 * et la zone mémoire spécifiée.
353 */
355 {
356 m_md->_setHostDeviceMemoryLocation(location);
357 }
358
359 //! Positionne l'emplacement physique de la zone mémoire.
361 {
362 return m_md->allocation_options.hostDeviceMemoryLocation();
363 }
364
365 public:
366
367 friend bool operator==(const AbstractArray<T>& rhs, const AbstractArray<T>& lhs)
368 {
369 return operator==(Span<const T>(rhs), Span<const T>(lhs));
370 }
371
372 friend bool operator!=(const AbstractArray<T>& rhs, const AbstractArray<T>& lhs)
373 {
374 return !(rhs == lhs);
375 }
376
377 friend bool operator==(const AbstractArray<T>& rhs, const Span<const T>& lhs)
378 {
379 return operator==(Span<const T>(rhs), lhs);
380 }
381
382 friend bool operator!=(const AbstractArray<T>& rhs, const Span<const T>& lhs)
383 {
384 return !(rhs == lhs);
385 }
386
387 friend bool operator==(const Span<const T>& rhs, const AbstractArray<T>& lhs)
388 {
389 return operator==(rhs, Span<const T>(lhs));
390 }
391
392 friend bool operator!=(const Span<const T>& rhs, const AbstractArray<T>& lhs)
393 {
394 return !(rhs == lhs);
395 }
396
397 friend std::ostream& operator<<(std::ostream& o, const AbstractArray<T>& val)
398 {
399 o << Span<const T>(val);
400 return o;
401 }
402
403 private:
404
405 using AbstractArrayBase::m_meta_data;
406
407 protected:
408
409 // NOTE: Ces deux champs sont utilisés pour l'affichage TTF de totalview.
410 // Si on modifie leur ordre il faut mettre à jour la partie correspondante
411 // dans l'afficheur totalview de Arcane.
412 T* m_ptr = nullptr;
413
414 protected:
415
416 //! Réserve le mémoire pour \a new_capacity éléments
417 void _reserve(Int64 new_capacity)
418 {
419 if (new_capacity <= m_md->capacity) {
420 // Dans le cas d'un allocateur collectif, on doit quand même faire un
421 // réalloc (à l'allocateur de gérer l'optimisation).
422 if (m_meta_data.is_collective_allocator) {
423 _internalRealloc(m_md->capacity, false);
424 }
425 return;
426 }
427 _internalRealloc(new_capacity, false);
428 }
429 /*!
430 * \brief Réalloue le tableau pour une nouvelle capacité égale à \a new_capacity.
431 *
432 * Si la nouvelle capacité est inférieure à l'ancienne, rien ne se passe.
433 */
434 template <typename PodType>
435 void _internalRealloc(Int64 new_capacity, bool compute_capacity, PodType pod_type, RunQueue* queue = nullptr)
436 {
437 // Remarque : Pour la mémoire partagée, si un des ptr est nullptr, alors
438 // il l'est pour tous les processus.
439 if (_isSharedNull()) {
440 if (new_capacity != 0 || m_meta_data.is_collective_allocator)
441 _internalAllocate(new_capacity, queue);
442 return;
443 }
444
445 Int64 acapacity = new_capacity;
446 if (compute_capacity) {
447 acapacity = m_md->capacity;
448 //std::cout << " REALLOC: want=" << wanted_size << " current_capacity=" << capacity << '\n';
449 while (new_capacity > acapacity)
450 acapacity = (acapacity == 0) ? 4 : (acapacity + 1 + acapacity / 2);
451 //std::cout << " REALLOC: want=" << wanted_size << " new_capacity=" << capacity << '\n';
452 }
453 // Si la nouvelle capacité est inférieure à la courante, ne fait rien
454 // (sauf pour un allocateur collectif).
455 if (acapacity <= m_md->capacity) {
456 if (m_meta_data.is_collective_allocator) {
457 _internalReallocate(m_md->capacity, pod_type, queue);
458 }
459 return;
460 }
461 _internalReallocate(acapacity, pod_type, queue);
462 }
463
464 void _internalRealloc(Int64 new_capacity, bool compute_capacity)
465 {
466 _internalRealloc(new_capacity, compute_capacity, IsPODType());
467 }
468
469 //! Réallocation pour un type POD
470 void _internalReallocate(Int64 new_capacity, TrueType, RunQueue* queue)
471 {
472 T* old_ptr = m_ptr;
473 Int64 old_capacity = m_md->capacity;
474 _directReAllocate(new_capacity, queue);
475 bool update = (new_capacity < old_capacity) || (m_ptr != old_ptr);
476 if (update) {
478 }
479 }
480
481 //! Réallocation pour un type complexe (non POD)
482 void _internalReallocate(Int64 new_capacity, FalseType, RunQueue* queue)
483 {
484 T* old_ptr = m_ptr;
485 ArrayMetaData* old_md = m_md;
486 AllocatedMemoryInfo old_mem_info = _currentMemoryInfo();
487 Int64 old_size = m_md->size;
488 _directAllocate(new_capacity, queue);
489 if (m_ptr != old_ptr) {
490 for (Int64 i = 0; i < old_size; ++i) {
491 new (m_ptr + i) T(old_ptr[i]);
492 old_ptr[i].~T();
493 }
494 m_md->nb_ref = old_md->nb_ref;
495 m_md->_deallocate(old_mem_info, queue);
497 }
498 }
499 // Libère la mémoire
500 void _internalDeallocate(RunQueue* queue = nullptr)
501 {
502 // Remarque : Pour la mémoire partagée, si un des ptr est nullptr, alors
503 // il l'est pour tous les processus.
504 if (!_isSharedNull())
505 m_md->_deallocate(_currentMemoryInfo(), queue);
506 if (m_md->is_not_null)
507 _deallocateMetaData(m_md);
508 }
509 void _internalAllocate(Int64 new_capacity, RunQueue* queue)
510 {
511 _directAllocate(new_capacity, queue);
512 m_md->nb_ref = _getNbRef();
514 }
515
516 void _copyFromMemory(const T* source)
517 {
518 m_md->_copyFromMemory(m_ptr, source, sizeof(T), _nullRunQueue());
519 }
520
521 private:
522
523 /*!
524 * \brief Effectue la première allocation.
525 *
526 * Si \a pre_allocated_buffer est non nul, on l'utilise comme buffer
527 * pour la première allocation. C'est à l'appelant de s'assurer que
528 * ce buffer est valide pour la capacité demandée. Le \a pre_allocated_buffer
529 * est utilisé notamment par l'allocateur de SmallArray.
530 */
531 void _directFirstAllocateWithAllocator(Int64 new_capacity, MemoryAllocationOptions options,
532 void* pre_allocated_buffer = nullptr)
533 {
534 IMemoryAllocator* wanted_allocator = options.allocator();
535 if (!wanted_allocator) {
536 wanted_allocator = ArrayMetaData::_defaultAllocator();
537 options.setAllocator(wanted_allocator);
538 }
539 _allocateMetaData();
540 m_md->allocation_options = options;
541 if (new_capacity > 0) {
542 if (!pre_allocated_buffer)
543 _allocateMP(new_capacity, options.runQueue());
544 else
545 _setMPCast(pre_allocated_buffer);
546 }
547 m_md->nb_ref = _getNbRef();
548 m_md->size = 0;
550 }
551
552 void _directAllocate(Int64 new_capacity, RunQueue* queue)
553 {
554 if (!m_md->is_not_null)
555 _allocateMetaData();
556 _allocateMP(new_capacity, queue);
557 }
558
559 void _allocateMP(Int64 new_capacity, RunQueue* queue)
560 {
561 _setMPCast(m_md->_allocate(new_capacity, typeSize(), queue));
562 }
563
564 void _directReAllocate(Int64 new_capacity, RunQueue* queue)
565 {
566 _setMPCast(m_md->_reallocate(_currentMemoryInfo(), new_capacity, typeSize(), queue));
567 }
568
569 public:
570
571 void changeAllocator(const MemoryAllocationOptions& options, RunQueue* queue)
572 {
573 _setMPCast(m_md->_changeAllocator(options, _currentMemoryInfo(), typeSize(), queue));
575 }
576
577 void changeAllocator(const MemoryAllocationOptions& options)
578 {
579 _setMPCast(m_md->_changeAllocator(options, _currentMemoryInfo(), typeSize(), _nullRunQueue()));
581 }
582
583 public:
584
585 void printInfos(std::ostream& o)
586 {
587 o << " Infos: size=" << m_md->size << " capacity=" << m_md->capacity << '\n';
588 }
589
590 protected:
591
592 //! Mise à jour des références
593 virtual void _updateReferences()
594 {
595 }
596 //! Mise à jour des références
598 {
599 return 1;
600 }
601 //! Ajoute \a n élément de valeur \a val à la fin du tableau
602 void _addRange(ConstReferenceType val, Int64 n)
603 {
604 Int64 s = m_md->size;
605 if ((s + n) > m_md->capacity)
606 _internalRealloc(s + n, true);
607 for (Int64 i = 0; i < n; ++i)
608 new (m_ptr + s + i) T(val);
609 m_md->size += n;
610 }
611
612 //! Ajoute \a n élément de valeur \a val à la fin du tableau
614 {
615 Int64 n = val.size();
616 const T* ptr = val.data();
617 Int64 s = m_md->size;
618 if ((s + n) > m_md->capacity)
619 _internalRealloc(s + n, true);
620 _createRange(s, s + n, ptr);
621 m_md->size += n;
622 }
623
624 //! Détruit l'instance si plus personne ne la référence
626 {
627 if (m_md->nb_ref == 0) {
628 _destroy();
629 _internalDeallocate(_nullRunQueue());
630 }
631 }
632 void _destroy()
633 {
634 _destroyRange(0, m_md->size, IsPODType());
635 }
636 void _destroyRange(Int64, Int64, TrueType)
637 {
638 // Rien à faire pour un type POD.
639 }
640 void _destroyRange(Int64 abegin, Int64 aend, FalseType)
641 {
642 if (abegin < 0)
643 abegin = 0;
644 for (Int64 i = abegin; i < aend; ++i)
645 m_ptr[i].~T();
646 }
647 void _createRangeDefault(Int64, Int64, TrueType)
648 {
649 }
650 void _createRangeDefault(Int64 abegin, Int64 aend, FalseType)
651 {
652 if (abegin < 0)
653 abegin = 0;
654 for (Int64 i = abegin; i < aend; ++i)
655 new (m_ptr + i) T();
656 }
657 void _createRange(Int64 abegin, Int64 aend, ConstReferenceType value, TrueType)
658 {
659 if (abegin < 0)
660 abegin = 0;
661 for (Int64 i = abegin; i < aend; ++i)
662 m_ptr[i] = value;
663 }
664 void _createRange(Int64 abegin, Int64 aend, ConstReferenceType value, FalseType)
665 {
666 if (abegin < 0)
667 abegin = 0;
668 for (Int64 i = abegin; i < aend; ++i)
669 new (m_ptr + i) T(value);
670 }
671 void _createRange(Int64 abegin, Int64 aend, const T* values)
672 {
673 if (abegin < 0)
674 abegin = 0;
675 for (Int64 i = abegin; i < aend; ++i) {
676 new (m_ptr + i) T(*values);
677 ++values;
678 }
679 }
680 void _fill(ConstReferenceType value)
681 {
682 for (Int64 i = 0, n = size(); i < n; ++i)
683 m_ptr[i] = value;
684 }
685 void _clone(const ThatClassType& orig_array)
686 {
687 Int64 that_size = orig_array.size();
688 _internalAllocate(that_size, _nullRunQueue());
689 m_md->size = that_size;
690 m_md->dim1_size = orig_array.m_md->dim1_size;
691 m_md->dim2_size = orig_array.m_md->dim2_size;
692 _createRange(0, that_size, orig_array.m_ptr);
693 }
694 template <typename PodType>
695 void _resizeHelper(Int64 s, PodType pod_type, RunQueue* queue)
696 {
697 if (s < 0)
698 s = 0;
699 if (s > m_md->size) {
700 this->_internalRealloc(s, false, pod_type, queue);
701 this->_createRangeDefault(m_md->size, s, pod_type);
702 }
703 else {
704 this->_destroyRange(s, m_md->size, pod_type);
705 if (m_meta_data.is_collective_allocator) {
706 this->_internalRealloc(s, false, pod_type, queue);
707 }
708 }
709 m_md->size = s;
710 }
711 void _resize(Int64 s)
712 {
713 _resizeHelper(s, IsPODType(), _nullRunQueue());
714 }
715 //! Redimensionne sans initialiser les nouvelles valeurs
716 void _resizeNoInit(Int64 s, RunQueue* queue = nullptr)
717 {
718 _resizeHelper(s, TrueType{}, queue);
719 }
720 void _clear()
721 {
722 this->_destroyRange(0, m_md->size, IsPODType());
723 m_md->size = 0;
724 }
725 //! Redimensionne et remplit les nouvelles valeurs avec \a value
726 void _resize(Int64 s, ConstReferenceType value)
727 {
728 if (s < 0)
729 s = 0;
730 if (s > m_md->size) {
731 this->_internalRealloc(s, false);
732 this->_createRange(m_md->size, s, value, IsPODType());
733 }
734 else {
735 this->_destroyRange(s, m_md->size, IsPODType());
736 if (m_meta_data.is_collective_allocator) {
737 this->_internalRealloc(s, false);
738 }
739 }
740 m_md->size = s;
741 }
742 void _copy(const T* rhs_begin, TrueType)
743 {
744 _copyFromMemory(rhs_begin);
745 }
746 void _copy(const T* rhs_begin, FalseType)
747 {
748 for (Int64 i = 0, n = m_md->size; i < n; ++i)
749 m_ptr[i] = rhs_begin[i];
750 }
751 void _copy(const T* rhs_begin)
752 {
753 _copy(rhs_begin, IsPODType());
754 }
755
756 /*!
757 * \brief Redimensionne l'instance et recopie les valeurs de \a rhs.
758 *
759 * Si la taille diminue, les éléments compris entre size() et rhs.size()
760 * sont détruits.
761 *
762 * \post size()==rhs.size()
763 */
765 {
766 const T* rhs_begin = rhs.data();
767 Int64 rhs_size = rhs.size();
768 const Int64 current_size = m_md->size;
769 T* abegin = m_ptr;
770 // Vérifie que \a rhs n'est pas un élément à l'intérieur de ce tableau
771 if (abegin >= rhs_begin && abegin < (rhs_begin + rhs_size))
772 ArrayMetaData::overlapError(abegin, m_md->size, rhs_begin, rhs_size);
773
774 if (rhs_size > current_size) {
775 this->_internalRealloc(rhs_size, false);
776 // Crée les nouveaux éléments
777 this->_createRange(m_md->size, rhs_size, rhs_begin + current_size);
778 // Copie les éléments déjà existant
779 _copy(rhs_begin);
780 m_md->size = rhs_size;
781 }
782 else {
783 this->_destroyRange(rhs_size, current_size, IsPODType{});
784 m_md->size = rhs_size;
785 _copy(rhs_begin);
786 }
787 }
788
789 /*!
790 * \brief Implémente l'opérateur d'assignement par déplacement.
791 *
792 * Cet appel n'est valide que pour les tableaux de type UniqueArray
793 * qui n'ont qu'une seule référence. Les infos de \a rhs sont directement
794 * copiés cette l'instance. En retour, \a rhs contient le tableau vide.
795 */
796 void _move(ThatClassType& rhs) ARCCORE_NOEXCEPT
797 {
798 if (&rhs == this)
799 return;
800
801 // Comme il n'y a qu'une seule référence sur le tableau actuel, on peut
802 // directement libérer la mémoire.
803 _destroy();
804 _internalDeallocate(_nullRunQueue());
805
806 _setMP(rhs.m_ptr);
807
808 _copyMetaData(rhs);
809
810 // Indique que \a rhs est vide.
811 rhs._reset();
812 }
813 /*!
814 * \brief Échange les valeurs de l'instance avec celles de \a rhs.
815 *
816 * Cet appel n'est valide que pour les tableaux de type UniqueArray
817 * et l'échange se fait uniquement par l'échange des pointeurs. L'opération
818 * est donc de complexité constante.
819 */
820 void _swap(ThatClassType& rhs) ARCCORE_NOEXCEPT
821 {
822 std::swap(m_ptr, rhs.m_ptr);
823 _swapMetaData(rhs);
824 }
825
826 void _shrink()
827 {
828 _shrink(size());
829 }
830
831 // Réalloue la mémoire pour avoir une capacité proche de \a new_capacity
832 void _shrink(Int64 new_capacity)
833 {
834 if (_isSharedNull())
835 return;
836 // On n'augmente pas la capacité avec cette méthode
837 if (new_capacity > this->capacity())
838 return;
839 if (new_capacity < 4)
840 new_capacity = 4;
841 _internalReallocate(new_capacity, IsPODType(), _nullRunQueue());
842 }
843
844 /*!
845 * \brief Réinitialise le tableau à un tableau vide.
846 * \warning Cette méthode n'est valide que pour les UniqueArray et pas
847 * les SharedArray.
848 */
849 void _reset()
850 {
851 _setToSharedNull();
852 }
853
854 constexpr Integer _clampSizeOffet(Int64 offset, Int32 asize) const
855 {
856 Int64 max_size = m_md->size - offset;
857 if (asize > max_size)
858 // On est certain de ne pas dépasser 32 bits car on est inférieur à asize.
859 asize = static_cast<Integer>(max_size);
860 return asize;
861 }
862
863 // Uniquement pour UniqueArray et UniqueArray2
864 void _assignFromArray(const AbstractArray<T>& rhs)
865 {
866 if (&rhs == this)
867 return;
868 Span<const T> rhs_span(rhs);
869 if (rhs.allocator() == this->allocator()) {
870 _resizeAndCopyView(rhs_span);
871 }
872 else {
873 _destroy();
874 _internalDeallocate(_nullRunQueue());
875 _reset();
876 _initFromAllocator(rhs.allocationOptions(), 0);
877 _initFromSpan(rhs_span);
878 }
879 }
880
881 protected:
882
883 void _setMP(TrueImpl* new_mp)
884 {
885 m_ptr = new_mp;
886 }
887
888 void _setMP2(TrueImpl* new_mp, ArrayMetaData* new_md)
889 {
890 _setMP(new_mp);
891 // Il ne faut garder le nouveau m_md que s'il est alloué
892 // sinon on risque d'avoir des références sur des objets temporaires
893 m_md = new_md;
894 if (!m_md->is_allocated_by_new)
895 m_md = &m_meta_data;
896 }
897
898 bool _isSharedNull()
899 {
900 return m_ptr == nullptr;
901 }
902
903 private:
904
905 void _setToSharedNull()
906 {
907 m_ptr = nullptr;
908 m_meta_data = ArrayMetaData();
909 m_md = &m_meta_data;
910 }
911 void _setMPCast(void* p)
912 {
913 _setMP(reinterpret_cast<TrueImpl*>(p));
914 }
915};
916
917/*---------------------------------------------------------------------------*/
918/*---------------------------------------------------------------------------*/
919
920} // namespace Arcane
921
922/*---------------------------------------------------------------------------*/
923/*---------------------------------------------------------------------------*/
924
925#endif
Types et fonctions associés aux classes SpanImpl, SmallSpan and Span.
Classe de base interne pour les tableaux.
static constexpr RunQueue * _nullRunQueue()
Méthode explicite pour une RunQueue nulle.
virtual bool _isUseOwnMetaData() const
Indique si m_md fait référence à m_meta_data.
Classe abstraite de base d'un vecteur.
void _addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
Integer capacity() const
Capacité (nombre d'éléments alloués) du vecteur.
void _addRange(Span< const T > val)
Ajoute n élément de valeur val à la fin du tableau.
void _internalSetHostDeviceMemoryLocation(eHostDeviceMemoryLocation location)
Positionne l'emplacement physique de la zone mémoire.
virtual void _updateReferences()
Mise à jour des références.
void _checkFreeMemory()
Détruit l'instance si plus personne ne la référence.
ConstReferenceType operator[](Int64 i) const
Elément d'indice i.
void dispose()
Libère la mémoire utilisée par le tableau.
AbstractArray()
Construit un vecteur vide avec l'allocateur par défaut.
Integer size() const
Nombre d'éléments du vecteur.
void _initFromSpan(const Span< const T > &view)
Initialise le tableau avec la vue view.
void _move(ThatClassType &rhs) ARCCORE_NOEXCEPT
Implémente l'opérateur d'assignement par déplacement.
void _initFromAllocator(MemoryAllocationOptions o, Int64 acapacity, void *pre_allocated_buffer=nullptr)
Construit un vecteur vide avec un allocateur spécifique a.
ArrayIterator< pointer > iterator
void _resize(Int64 s, ConstReferenceType value)
Redimensionne et remplit les nouvelles valeurs avec value.
void setMemoryLocationHint(eMemoryLocationHint new_hint)
Modifie les informations sur la localisation mémoire.
void _internalReallocate(Int64 new_capacity, FalseType, RunQueue *queue)
Réallocation pour un type complexe (non POD)
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
eHostDeviceMemoryLocation hostDeviceMemoryLocation() const
Positionne l'emplacement physique de la zone mémoire.
Int64 largeSize() const
Nombre d'éléments du vecteur (en 64 bits)
bool contains(ConstReferenceType v) const
Vrai si le tableau contient l'élément de valeur v.
Int64 largeCapacity() const
Capacité (nombre d'éléments alloués) du vecteur (en 64 bits)
Int64 largeLength() const
Nombre d'éléments du vecteur (en 64 bits)
void _reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void _resizeAndCopyView(Span< const T > rhs)
Redimensionne l'instance et recopie les valeurs de rhs.
virtual Integer _getNbRef()
Mise à jour des références.
ArrayIterator< const_pointer > const_iterator
void _resizeNoInit(Int64 s, RunQueue *queue=nullptr)
Redimensionne sans initialiser les nouvelles valeurs.
AbstractArray(ThatClassType &&rhs) ARCCORE_NOEXCEPT
Constructeur par déplacement. Ne doit être utilisé que par UniqueArray.
void _internalRealloc(Int64 new_capacity, bool compute_capacity, PodType pod_type, RunQueue *queue=nullptr)
Réalloue le tableau pour une nouvelle capacité égale à new_capacity.
void _swap(ThatClassType &rhs) ARCCORE_NOEXCEPT
Échange les valeurs de l'instance avec celles de rhs.
ConstReferenceType operator()(Int64 i) const
Elément d'indice i.
void _reset()
Réinitialise le tableau à un tableau vide.
void _internalReallocate(Int64 new_capacity, TrueType, RunQueue *queue)
Réallocation pour un type POD.
Integer length() const
Nombre d'éléments du vecteur.
Informations sur une zone mémoire allouée.
String debugName() const
void setDebugName(const String &name)
Itérateur sur les classes tableau de Arccore.
bool is_not_null
Indique si cette instance n'est pas l'instance nulle (partagée par tous les SharedArray)
Int64 size
Nombre d'éléments du tableau (pour les tableaux 1D)
Int32 nb_ref
Nombre de références sur l'instance.
bool is_allocated_by_new
Indique is cette instance a été allouée par l'opérateur new.
Vue constante d'un tableau de type T.
Interface d'un allocateur pour la mémoire.
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
Definition Span.h:537
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:325
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Chaîne de caractères unicode.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
eMemoryLocationHint
Indices sur la localisation mémoire attendue.
eHostDeviceMemoryLocation
Localisation physique d'une adresse mémoire.
std::int32_t Int32
Type entier signé sur 32 bits.