Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
SharedMemoryParallelMng.cc
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/* SharedMemoryParallelMng.cc (C) 2000-2026 */
9/* */
10/* Implementation of messages in shared memory mode. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/parallel/thread/SharedMemoryParallelMng.h"
15
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/NotSupportedException.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/TraceInfo.h"
20#include "arcane/utils/NumericTypes.h"
21#include "arcane/utils/ArgumentException.h"
22#include "arcane/utils/FatalErrorException.h"
23#include "arcane/utils/ITraceMng.h"
24#include "arcane/utils/SmallArray.h"
25
26#include "arcane/parallel/IStat.h"
27
28#include "arcane/parallel/thread/SharedMemoryParallelDispatch.h"
29#include "arcane/parallel/thread/ISharedMemoryMessageQueue.h"
30#include "arcane/parallel/thread/internal/SharedMemoryMachineShMemWinBaseInternalCreator.h"
31#include "arcane/parallel/thread/internal/SharedMemoryContigMachineShMemWinBaseInternal.h"
32#include "arcane/parallel/thread/internal/SharedMemoryMachineShMemWinBaseInternal.h"
33
34#include "arcane/core/Timer.h"
35#include "arcane/core/IIOMng.h"
36#include "arcane/core/ISerializeMessageList.h"
37#include "arcane/core/IItemFamily.h"
38#include "arcane/core/internal/SerializeMessage.h"
39#include "arcane/core/internal/ParallelMngInternal.h"
40#include "arcane/core/internal/MachineShMemWinMemoryAllocator.h"
41
42#include "arcane/impl/TimerMng.h"
43#include "arcane/impl/ParallelReplication.h"
44#include "arcane/impl/internal/ParallelMngUtilsFactoryBase.h"
45
46#include "arccore/message_passing/RequestListBase.h"
47#include "arccore/message_passing/internal/SerializeMessageList.h"
48
49#include "arcane/parallel/thread/SharedMemoryMessageQueue.h"
50
51#include <map>
52
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55
56namespace Arcane
57{
58extern "C++" ARCANE_IMPL_EXPORT IIOMng*
59arcaneCreateIOMng(IParallelMng* psm);
60}
61
63{
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
73{
75
76 public:
77
78 explicit RequestList(SharedMemoryParallelMng* pm)
79 : m_parallel_mng(pm)
80 , m_message_queue(pm->m_message_queue)
81 , m_local_rank(m_parallel_mng->commRank())
82 {}
83
84 public:
85
86 void _wait(Parallel::eWaitType wait_type) override
87 {
88 switch (wait_type) {
89 case Parallel::WaitAll:
90 m_message_queue->waitAll(m_local_rank, _requests());
91 break;
93 m_message_queue->waitSome(m_local_rank, _requests(), _requestsDone(), false);
94 break;
96 m_message_queue->waitSome(m_local_rank, _requests(), _requestsDone(), true);
97 break;
98 }
99 }
100
101 private:
102
103 SharedMemoryParallelMng* m_parallel_mng;
104 ISharedMemoryMessageQueue* m_message_queue;
105 Int32 m_local_rank;
106 };
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
112: public ParallelMngInternal
113{
114 public:
115
116 explicit Impl(SharedMemoryParallelMng* pm, SharedMemoryMachineShMemWinBaseInternalCreator* window_creator)
117 : ParallelMngInternal(pm)
118 , m_parallel_mng(pm)
119 , m_window_creator(window_creator)
120 , m_alloc(makeRef(new MachineShMemWinMemoryAllocator(pm)))
121 {}
122
123 ~Impl() override = default;
124
125 public:
126
127 Int32 masterParallelIORank() const override { return 0; }
128 Int32 nbSendersToMasterParallelIO() const override { return m_parallel_mng->commSize(); }
129
130 void initializeWindowCreator() override {}
131
133 {
134 return true;
135 }
136
138 {
139 return makeRef(m_window_creator->createWindow(m_parallel_mng->commRank(), sizeof_segment, sizeof_type));
140 }
141
143 {
144 return makeRef(m_window_creator->createDynamicWindow(m_parallel_mng->commRank(), sizeof_segment, sizeof_type));
145 }
146
148 {
149 return MemoryAllocationOptions{ m_alloc.get() };
150 }
151
153 {
154 return m_window_creator->machineRanks();
155 }
156
157 void machineBarrier() override
158 {
159 m_window_creator->machineBarrier();
160 }
161
162 private:
163
164 SharedMemoryParallelMng* m_parallel_mng;
167};
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172SharedMemoryParallelMng::
173SharedMemoryParallelMng(const SharedMemoryParallelMngBuildInfo& build_info)
174: ParallelMngDispatcher(ParallelMngDispatcherBuildInfo(build_info.rank, build_info.nb_rank))
175, m_trace(build_info.trace_mng)
176, m_thread_mng(build_info.thread_mng)
177, m_sequential_parallel_mng(build_info.sequential_parallel_mng)
178, m_timer_mng(nullptr)
179, m_replication(new ParallelReplication())
180, m_world_parallel_mng(build_info.world_parallel_mng)
181, m_io_mng(nullptr)
182, m_message_queue(build_info.message_queue)
183, m_is_parallel(build_info.nb_rank != 1)
184, m_rank(build_info.rank)
185, m_nb_rank(build_info.nb_rank)
186, m_is_initialized(false)
187, m_stat(Parallel::createDefaultStat())
188, m_thread_barrier(build_info.thread_barrier)
189, m_all_dispatchers(build_info.all_dispatchers)
190, m_sub_builder_factory(build_info.sub_builder_factory)
191, m_parent_container_ref(build_info.container)
192, m_mpi_communicator(build_info.communicator)
193, m_utils_factory(createRef<ParallelMngUtilsFactoryBase>())
194, m_parallel_mng_internal(new Impl(this, build_info.window_creator))
195{
196 if (!m_world_parallel_mng)
197 m_world_parallel_mng = this;
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203SharedMemoryParallelMng::
204~SharedMemoryParallelMng()
205{
206 delete m_parallel_mng_internal;
207 delete m_replication;
208 m_sequential_parallel_mng.reset();
209 delete m_io_mng;
210 delete m_timer_mng;
211 delete m_stat;
212}
213
214/*---------------------------------------------------------------------------*/
215/*---------------------------------------------------------------------------*/
216
217namespace
218{
219 // Class to create the different dispatchers
220 class DispatchCreator
221 {
222 public:
223
224 DispatchCreator(ITraceMng* tm, SharedMemoryParallelMng* mpm,
225 ISharedMemoryMessageQueue* message_queue,
226 SharedMemoryAllDispatcher* all_dispatchers)
227 : m_tm(tm)
228 , m_mpm(mpm)
229 , m_message_queue(message_queue)
230 , m_all_dispatchers(all_dispatchers)
231 {}
232
233 public:
234
235 template <typename DataType> SharedMemoryParallelDispatch<DataType>*
236 create()
237 {
238 ISharedMemoryMessageQueue* tmq = m_message_queue;
239 SharedMemoryAllDispatcher* ad = m_all_dispatchers;
240 auto& field = ad->instance((DataType*)nullptr);
241 return new SharedMemoryParallelDispatch<DataType>(m_tm, m_mpm, tmq, field);
242 }
243
244 ITraceMng* m_tm;
245 SharedMemoryParallelMng* m_mpm;
246 ISharedMemoryMessageQueue* m_message_queue;
247 SharedMemoryAllDispatcher* m_all_dispatchers;
248 };
249} // namespace
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
255build()
256{
257 m_message_queue->setTraceMng(m_rank, traceMng());
258 m_timer_mng = new TimerMng(traceMng());
259
260 DispatchCreator creator(m_trace.get(), this, m_message_queue, m_all_dispatchers);
261 this->createDispatchers(creator);
262
263 m_io_mng = arcaneCreateIOMng(this);
264}
265
266/*----------------------------------------------------------------------------*/
267/*---------------------------------------------------------------------------*/
268
271{
272 Trace::Setter mci(m_trace.get(), "Thread");
273 if (m_is_initialized) {
274 m_trace->warning() << "SharedMemoryParallelMng already initialized";
275 return;
276 }
277
278 m_is_initialized = true;
279}
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
286{
287 return m_utils_factory->createGetVariablesValuesOperation(this)._release();
288}
289
292{
293 return m_utils_factory->createTransferValuesOperation(this)._release();
294}
295
298{
299 return m_utils_factory->createExchanger(this)._release();
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
308void SharedMemoryParallelMng::
309sendSerializer(ISerializer* values, Int32 dest_rank)
310{
311 auto p2p_message = buildMessage(dest_rank, Parallel::Blocking);
312 Request r = m_message_queue->addSend(p2p_message, SendBufferInfo(values));
313 m_message_queue->waitAll(m_rank, ArrayView<Request>(1, &r));
314}
315
316/*---------------------------------------------------------------------------*/
317/*---------------------------------------------------------------------------*/
318
319Parallel::Request SharedMemoryParallelMng::
320sendSerializer(ISerializer* values, Int32 rank, ByteArray& bytes)
321{
322 ARCANE_UNUSED(bytes);
323 return m_message_queue->addSend(buildMessage(rank, Parallel::Blocking), SendBufferInfo(values));
324}
325
326/*---------------------------------------------------------------------------*/
327/*---------------------------------------------------------------------------*/
328
331{
332 return m_utils_factory->createSendSerializeMessage(this, rank)._release();
333}
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
337
338void SharedMemoryParallelMng::
339broadcastSerializer(ISerializer* values, Int32 rank)
340{
341 // Basic implementation for now.
342 // The rank that broadcasts sends the message to everyone.
343 if (m_rank == rank) {
345 for (Int32 i = 0; i < m_nb_rank; ++i) {
346 if (i != m_rank) {
347 requests.add(m_message_queue->addSend(buildMessage(i, Parallel::NonBlocking), SendBufferInfo(values)));
348 }
349 }
350 m_message_queue->waitAll(m_rank, requests);
351 }
352 else {
353 recvSerializer(values, rank);
354 }
355}
356
357/*---------------------------------------------------------------------------*/
358/*---------------------------------------------------------------------------*/
359
360void SharedMemoryParallelMng::
361recvSerializer(ISerializer* values, Int32 rank)
362{
363 auto p2p_message = buildMessage(rank, Parallel::Blocking);
364 Request r = m_message_queue->addReceive(p2p_message, ReceiveBufferInfo(values));
365 m_message_queue->waitAll(m_rank, ArrayView<Request>(1, &r));
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
373{
374 return m_utils_factory->createReceiveSerializeMessage(this, rank)._release();
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
382{
383 ARCANE_UNUSED(requests);
384 throw NotImplementedException(A_FUNCINFO);
385}
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
389
392{
393 if (m_stat)
394 m_stat->print(m_trace.get());
395}
396
397/*---------------------------------------------------------------------------*/
398/*---------------------------------------------------------------------------*/
399
401barrier()
402{
403 m_thread_barrier->wait();
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
411{
412 Real begin_time = platform::getRealTime();
413 m_message_queue->waitAll(m_rank, requests);
414 Real end_time = platform::getRealTime();
415 m_stat->add("WaitAll", (end_time - begin_time), 0);
416}
417
418/*---------------------------------------------------------------------------*/
419/*---------------------------------------------------------------------------*/
420
421ISerializeMessageList* SharedMemoryParallelMng::
422_createSerializeMessageList()
423{
424 return new MP::internal::SerializeMessageList(messagePassingMng());
425}
426
427/*---------------------------------------------------------------------------*/
428/*---------------------------------------------------------------------------*/
429
431probe(const PointToPointMessageInfo& message)
432{
433 PointToPointMessageInfo p2p_message(message);
434 p2p_message.setEmiterRank(MessageRank(m_rank));
435 return m_message_queue->probe(p2p_message);
436}
437
438/*---------------------------------------------------------------------------*/
439/*---------------------------------------------------------------------------*/
440
443{
444 PointToPointMessageInfo p2p_message(message);
445 p2p_message.setEmiterRank(MessageRank(m_rank));
446 return m_message_queue->legacyProbe(p2p_message);
447}
448
449/*---------------------------------------------------------------------------*/
450/*---------------------------------------------------------------------------*/
451
452auto SharedMemoryParallelMng::
453sendSerializer(const ISerializer* values, const PointToPointMessageInfo& message) -> Request
454{
455 auto p2p_message = buildMessage(message);
456 return m_message_queue->addSend(p2p_message, SendBufferInfo(values));
457}
458
459/*---------------------------------------------------------------------------*/
460/*---------------------------------------------------------------------------*/
461
462auto SharedMemoryParallelMng::
463receiveSerializer(ISerializer* values, const PointToPointMessageInfo& message) -> Request
464{
465 auto p2p_message = buildMessage(message);
466 return m_message_queue->addReceive(p2p_message, ReceiveBufferInfo(values));
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
474{
475 return m_utils_factory->createSynchronizer(this, family)._release();
476}
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
480
482createSynchronizer(const ItemGroup& group)
483{
484 return m_utils_factory->createSynchronizer(this, group)._release();
485}
486
487/*---------------------------------------------------------------------------*/
488/*---------------------------------------------------------------------------*/
489
492{
493 return m_utils_factory->createTopology(this)._release();
494}
495
496/*---------------------------------------------------------------------------*/
497/*---------------------------------------------------------------------------*/
498
500replication() const
501{
502 return m_replication;
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
510{
511 delete m_replication;
512 m_replication = v;
513}
514
515/*---------------------------------------------------------------------------*/
516/*---------------------------------------------------------------------------*/
517
518IParallelMng* SharedMemoryParallelMng::
519_createSubParallelMng(Int32ConstArrayView kept_ranks)
520{
521 ARCANE_UNUSED(kept_ranks);
522 // We cannot implement this method because we go through
523 // IParallelMngContainer::_createParallelMng() which obligatorily
524 // creates a 'Ref<IParallelMng>'.
525 ARCANE_THROW(NotSupportedException, "Use createSubParallelMngRef() instead");
526}
527
528/*---------------------------------------------------------------------------*/
529/*---------------------------------------------------------------------------*/
530
533{
534 if (kept_ranks.empty())
535 ARCANE_FATAL("kept_ranks is empty");
536 ARCANE_CHECK_POINTER(m_sub_builder_factory);
537
539 Int32 nb_rank = kept_ranks.size();
540
541 // Check if I am in the list of kept ranks and if so
542 // determine my rank in the created IParallelMng
543 Int32 my_new_rank = (-1);
544 for (Integer i = 0; i < nb_rank; ++i)
545 if (kept_ranks[i] == m_rank) {
546 my_new_rank = i;
547 break;
548 }
549
550 barrier();
551 // Rank 0 creates the builder
552 if (m_rank == 0) {
553 builder = m_sub_builder_factory->_createParallelMngBuilder(nb_rank, m_mpi_communicator, m_mpi_communicator);
554 // Positions the builder for everyone
555 m_all_dispatchers->m_create_sub_parallel_mng_info.m_builder = builder;
556 }
557 barrier();
558
559 builder = m_all_dispatchers->m_create_sub_parallel_mng_info.m_builder;
560 ARCANE_CHECK_POINTER(builder.get());
561
562 Ref<IParallelMng> new_parallel_mng;
563 if (my_new_rank >= 0) {
564 new_parallel_mng = builder->_createParallelMng(my_new_rank, traceMng());
565 //auto* new_sm = dynamic_cast<SharedMemoryParallelMng*>(new_parallel_mng.get());
566 //if (new_sm)
567 //new_sm->m_mpi_communicator = m_mpi_communicator;
568 }
569 barrier();
570 // Here, everyone has created their IParallelMng. We can therefore
571 // delete the reference to the builder.
572 // TODO: a reference counter must be added to the builder
573 // otherwise it will never be destroyed.
574 if (m_rank == 0) {
575 m_all_dispatchers->m_create_sub_parallel_mng_info.m_builder.reset();
576 }
577 barrier();
578
579 return new_parallel_mng;
580}
581
582/*---------------------------------------------------------------------------*/
583/*---------------------------------------------------------------------------*/
584
591
592/*---------------------------------------------------------------------------*/
593/*---------------------------------------------------------------------------*/
594
595Ref<IParallelMng> SharedMemoryParallelMng::
596sequentialParallelMngRef()
597{
598 return m_sequential_parallel_mng;
599}
600
603{
604 return m_sequential_parallel_mng.get();
605}
606
607/*---------------------------------------------------------------------------*/
608/*---------------------------------------------------------------------------*/
609
611buildMessage(const PointToPointMessageInfo& orig_message)
612{
613 PointToPointMessageInfo p2p_message{ orig_message };
614 p2p_message.setEmiterRank(MessageRank(m_rank));
615 return p2p_message;
616}
617
618/*---------------------------------------------------------------------------*/
619/*---------------------------------------------------------------------------*/
620
621PointToPointMessageInfo SharedMemoryParallelMng::
622buildMessage(Int32 dest, Parallel::eBlockingType blocking_mode)
623{
624 return buildMessage({ MessageRank(dest), blocking_mode });
625}
626
627/*---------------------------------------------------------------------------*/
628/*---------------------------------------------------------------------------*/
629
635
636/*---------------------------------------------------------------------------*/
637/*---------------------------------------------------------------------------*/
638
639} // End namespace Arcane::MessagePassing
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Modifiable view of an array of type T.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
constexpr bool empty() const noexcept
true if the array is empty (size()==0)
Operations to access variable values from another subdomain.
Interface of the input/output manager.
Definition IIOMng.h:37
Interface of an entity family.
Definition IItemFamily.h:85
Information exchange between processors.
Interface of the parallelism manager for a subdomain.
Brief information on parallel subdomain replication.
Information on the computing core allocation topology.
Sends values across different processors.
Interface of a variable synchronization service.
Mesh entity group.
Definition ItemGroup.h:51
Information about the source of a message.
Information for sending/receiving a point-to-point message.
void setEmiterRank(MessageRank rank)
Positions the message sender rank.
bool isMachineShMemWinAvailable() override
Method allowing to know if shared memory mode is supported.
MemoryAllocationOptions machineShMemWinMemoryAllocator() override
Method allowing retrieval of a shared memory allocator.
void initializeWindowCreator() override
Method allowing the initialization of the windowCreator specific to the implementation.
Ref< IMachineShMemWinBaseInternal > createMachineShMemWinBase(Int64 sizeof_segment, Int32 sizeof_type) override
Method allowing the creation of a dynamic memory window on the node.
ConstArrayView< Int32 > machineRanks() override
Method allowing retrieval of the ranks of the sub-domains of the computing node.
Ref< IContigMachineShMemWinBaseInternal > createContigMachineShMemWinBase(Int64 sizeof_segment, Int32 sizeof_type) override
Method allowing the creation of a memory window on the node.
void machineBarrier() override
Method allowing a barrier for the sub-domains of the computing node.
Implementation of IRequestList for SharedMemoryParallelMng.
void _wait(Parallel::eWaitType wait_type) override
Performs the wait or test.
IParallelTopology * createTopology() override
Creates an instance containing information about the rank topology of this manager.
IGetVariablesValuesParallelOperation * createGetVariablesValuesOperation() override
Returns an operation to retrieve the values of a variable on the entities of another subdomain.
Ref< Parallel::IRequestList > createRequestListRef() override
Creates a request list for this manager.
void build() override
Constructs the instance.
void printStats() override
Prints statistics related to this parallelism manager.
void initialize() override
Initializes the parallelism manager.
void setReplication(IParallelReplication *v) override
Sets the Replication Information.
PointToPointMessageInfo buildMessage(Int32 dest, MP::eBlockingType is_blocking)
Constructs a message with destination dest.
void waitAllRequests(ArrayView< Request > requests) override
Blocks while waiting for the rvalues requests to complete.
Ref< IParallelMngUtilsFactory > _internalUtilsFactory() const override
Factory for utility functions.
IVariableSynchronizer * createSynchronizer(IItemFamily *family) override
Returns an interface for synchronizing variables on the group of the family.
MessageId probe(const PointToPointMessageInfo &message) override
Probes if messages are available.
ISerializeMessage * createSendSerializer(Int32 rank) override
Creates a non-blocking message to send serialized data to rank rank.
ITraceMng * traceMng() const override
Trace manager associated to this instance.
IParallelMng * sequentialParallelMng() override
Returns a sequential parallelism manager.
IParallelExchanger * createExchanger() override
Returns an interface for transferring messages between processors.
void freeRequests(ArrayView< Parallel::Request > requests) override
Frees the requests.
ISerializeMessage * createReceiveSerializer(Int32 rank) override
Creates a non-blocking message to receive serialized data from rank rank.
Ref< IParallelMng > createSubParallelMngRef(Int32ConstArrayView kept_ranks) override
Creates a new parallelism manager for a subset of ranks.
ITransferValuesParallelOperation * createTransferValuesOperation() override
Returns an operation to transfer values between subdomains.
MessageSourceInfo legacyProbe(const PointToPointMessageInfo &message) override
Probes if messages are available.
IParallelReplication * replication() const override
Replication information.
Redirects the message management of sub-domains according to the argument type.
IMessagePassingMng * messagePassingMng() const override
Associated Arccore message passing manager.
Base class of a factory for IParallelMng utility functions.
Brief information on parallel subdomain replication.
InstanceType * get() const
Associated instance or nullptr if none.
Reference to an instance.
Timer manager.
Definition TimerMng.h:40
1D data vector with value semantics (STL style).
Declarations of types and methods used by message exchange mechanisms.
@ WaitSome
Wait until all messages in the list are processed.
eBlockingType
Type indicating whether a message is blocking or not.
Concurrency implementation.
Real getRealTime()
Real time used in seconds.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Ref< TrueType > createRef(Args &&... args)
Creates an instance of type TrueType with arguments Args and returns a reference to it.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
Array< Byte > ByteArray
Dynamic one-dimensional array of characters.
Definition UtilsTypes.h:115
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.