Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
SerializedData.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/* SerializedData.cc (C) 2000-2024 */
9/* */
10/* Serialized data. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/ISerializedData.h"
15
17
18#include "arcane/utils/Ref.h"
19#include "arcane/utils/NotImplementedException.h"
20#include "arcane/utils/NotSupportedException.h"
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/IHashAlgorithm.h"
23#include "arcane/utils/CheckedConvert.h"
24#include "arcane/utils/Array.h"
25#include "arcane/utils/ArrayShape.h"
26
27#include "arcane/core/ISerializer.h"
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32namespace Arcane
33{
34
35namespace
36{
37 const Int64 SERIALIZE_MAGIC_NUMBER = 0x6b90ac81;
38}
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43/*!
44 * \internal
45 * \brief Interface for serialized data.
46 */
47class SerializedData
49, public ISerializedData
50{
52
53 public:
54
55 SerializedData();
56 SerializedData(eDataType base_data_type, Int64 memory_size,
57 Integer nb_dimension, Int64 nb_element, Int64 nb_base_element,
58 bool is_multi_size, Int64ConstArrayView extents, const ArrayShape& shape);
59
60 public:
61
62 eDataType baseDataType() const override { return m_base_data_type; }
63 Integer nbDimension() const override { return m_nb_dimension; }
64 Int64 nbElement() const override { return m_nb_element; }
65 bool isMultiSize() const override { return m_is_multi_size; }
66 Int64 memorySize() const override { return m_memory_size; }
67 Int64ConstArrayView extents() const override { return m_extents; }
68 ArrayShape shape() const override { return m_shape; }
69 Int64 nbBaseElement() const override { return m_nb_base_element; }
70 ByteConstArrayView buffer() const override { return m_const_buffer.constSmallView(); }
71 ByteArrayView buffer() override { return m_buffer.smallView(); }
72 Span<const Byte> bytes() const override { return m_const_buffer; }
73 Span<const Byte> constBytes() const override { return m_const_buffer; }
74 Span<Byte> bytes() override { return m_buffer; }
75 void setBuffer(ByteArrayView buffer) override;
76 void setBuffer(ByteConstArrayView buffer) override;
79 Span<Byte> writableBytes() override { return m_buffer; }
80 void setWritableBytes(Span<Byte> bytes) override;
82 void allocateMemory(Int64 size) override;
83
84 public:
85
86 void serialize(ISerializer* buffer) override;
87 void serialize(ISerializer* buffer) const override;
88
89 public:
90
91 void computeHash(IHashAlgorithm* algo, ByteArray& output) const override;
92
93 private:
94
95 eDataType m_base_data_type;
96 Int64 m_memory_size;
97 Integer m_nb_dimension;
98 Int64 m_nb_element;
99 Int64 m_nb_base_element;
100 bool m_is_multi_size;
101 // TODO: remove the 'm_dimensions' field, but this implies changing
102 // the value of computeHash(), so we need to determine the best time
103 // to do it.
104 UniqueArray<Int32> m_dimensions;
105 UniqueArray<Int64> m_extents;
106 Int64 m_element_size;
107 Span<Byte> m_buffer;
108 Span<const Byte> m_const_buffer;
109 UniqueArray<Byte> m_stored_buffer;
110 ArrayShape m_shape;
111
112 private:
113
114 void _serialize(ISerializer* sbuf) const;
115 void _serializeRead(ISerializer* sbuf);
116 void _copyExtentsToDimensions();
117};
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122SerializedData::
123SerializedData()
124: m_base_data_type(DT_Unknown)
125, m_memory_size(0)
126, m_nb_dimension(0)
127, m_nb_element(0)
128, m_nb_base_element(0)
129, m_is_multi_size(false)
130, m_element_size(0)
131{
132}
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
137SerializedData::
138SerializedData(eDataType base_data_type, Int64 memory_size,
139 Integer nb_dimension, Int64 nb_element, Int64 nb_base_element,
140 bool is_multi_size, Int64ConstArrayView extents, const ArrayShape& shape)
141: m_base_data_type(base_data_type)
142, m_memory_size(memory_size)
143, m_nb_dimension(nb_dimension)
144, m_nb_element(nb_element)
145, m_nb_base_element(nb_base_element)
146, m_is_multi_size(is_multi_size)
147, m_extents(extents)
148, m_element_size(dataTypeSize(m_base_data_type))
149, m_shape(shape)
150{
151 _copyExtentsToDimensions();
152 if (!is_multi_size && shape.nbDimension() == 0) {
153 if (nb_dimension == 1) {
154 m_shape.setNbDimension(1);
155 m_shape.setDimension(0, 1);
156 }
157 else if (nb_dimension > 1) {
158 m_shape.setNbDimension(nb_dimension - 1);
159 for (Int32 i = 1; i < nb_dimension; ++i)
160 m_shape.setDimension(i - 1, CheckedConvert::toInt32(extents[i]));
161 }
162 }
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
168void SerializedData::
169_copyExtentsToDimensions()
170{
171 Integer n = m_extents.size();
172 m_dimensions.resize(n);
173 // Exceptions should not be thrown if bounds are exceeded, otherwise
174 // the code will throw an exception as soon as the number of array elements
175 // exceeds 32 bits. This is not very serious if the values of 'm_dimensions'
176 // are invalid because they are only used in computeHash() to
177 // maintain compatibility.
178 for (Integer i = 0; i < n; ++i)
179 m_dimensions[i] = static_cast<Int32>(m_extents[i]);
180}
181
182/*---------------------------------------------------------------------------*/
183/*---------------------------------------------------------------------------*/
184
187{
188 setBytes(Span<Byte>(buffer));
189}
190
191/*---------------------------------------------------------------------------*/
192/*---------------------------------------------------------------------------*/
193
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
205{
206 m_buffer = buffer;
207 m_const_buffer = buffer;
208 m_stored_buffer.clear();
209 m_memory_size = buffer.size();
210}
211
212/*---------------------------------------------------------------------------*/
213/*---------------------------------------------------------------------------*/
214
217{
218 m_const_buffer = buffer;
219 m_buffer = Span<Byte>();
220 m_stored_buffer.clear();
221 m_memory_size = buffer.size();
222}
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
229{
230 m_stored_buffer = UniqueArray<Byte>(size);
231 m_buffer = m_stored_buffer;
232 m_const_buffer = m_stored_buffer.view();
233 m_memory_size = size;
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
240computeHash(IHashAlgorithm* algo, ByteArray& output) const
241{
242 // TODO: implement 64-bit support, but this changes the hash.
243 algo->computeHash64(m_const_buffer, output);
244 const Byte* ptr = reinterpret_cast<const Byte*>(m_dimensions.data());
245 Integer msize = CheckedConvert::multiply(m_dimensions.size(), (Integer)sizeof(Integer));
246 ByteConstArrayView dim_bytes(msize, ptr);
247 algo->computeHash64(dim_bytes, output);
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252/*!
253 * \todo Do not use the DT_Byte type for serialization, but * the true base
254 * type: this type can be used with MPI, and in this * case, if the machines
255 * are heterogeneous, the type information is lost * and the put operation
256 * may not match.
257 */
259serialize(ISerializer* sbuf) const
260{
261 _serialize(sbuf);
262}
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
269{
270 ISerializer::eMode mode = sbuf->mode();
271
272 switch (mode) {
273 case ISerializer::ModeReserve:
274 _serialize(sbuf);
275 break;
277 _serialize(sbuf);
278 break;
280 switch (sbuf->readMode()) {
282 _serializeRead(sbuf);
283 break;
286 break;
287 }
288 break;
289 }
290}
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
294
295void SerializedData::
296_serializeRead(ISerializer* sbuf)
297{
298 Int64 magic_number = sbuf->getInt64(); // Magic number for verification
299 if (magic_number != SERIALIZE_MAGIC_NUMBER)
300 ARCANE_FATAL("Bad magic number for SerializedData '{0}", magic_number);
301
302 Int32 version = sbuf->getInt32(); // For the version number
303 if (version != 1)
304 ARCANE_FATAL("Bad magic number for SerializedData '{0}", magic_number);
305
306 m_base_data_type = (eDataType)sbuf->getInteger(); // For m_base_data_type
307 m_memory_size = sbuf->getInt64(); // For m_memory_size
308 m_nb_dimension = sbuf->getInteger(); // For m_nb_dimension
309 m_nb_element = sbuf->getInt64(); // For m_nb_element
310 m_nb_base_element = sbuf->getInt64(); // For m_nb_base_element
311 m_is_multi_size = sbuf->getInteger(); // For m_is_multi_size
312 m_element_size = sbuf->getInt64(); // For m_element_size
313
314 // Reading dimensions
315 Int64 dimensions_size = sbuf->getInt64();
316 m_extents.resize(dimensions_size);
317 sbuf->getSpan(m_extents);
318 _copyExtentsToDimensions();
319
320 // Reading 'm_shape'
321 Int32 shape_nb_dim = sbuf->getInt32(); // For m_shape.nbDimension()
322 std::array<Int32, ArrayShape::MAX_NB_DIMENSION> shape_dims_buf;
323 Span<Int32> shape_dims(shape_dims_buf.data(), shape_nb_dim);
324 sbuf->getSpan(shape_dims); // For the dimensions
325 m_shape.setDimensions(shape_dims);
326
327 Int64 buffer_size = sbuf->getInt64();
328 m_stored_buffer.resize(buffer_size);
329 sbuf->getSpan(m_stored_buffer); // For the data
330 m_buffer = m_stored_buffer;
331 m_const_buffer = m_buffer;
332}
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
336/*!
337 * \todo Do not use the DT_Byte type for serialization, but the true base
338 * type: this type can be used with MPI, and in this case, if the machines
339 * are heterogeneous, the type information is lost and the put operation may
340 * not match.
341 */
342void SerializedData::
343_serialize(ISerializer* sbuf) const
344{
345 ISerializer::eMode mode = sbuf->mode();
346 if (m_extents.size() != m_dimensions.size())
347 ARCANE_FATAL("Incoherence between extents ({0}) and dimensions ({1})",
348 m_extents.size(), m_dimensions.size());
349
350 switch (mode) {
351 case ISerializer::ModeReserve:
352 sbuf->reserveInt64(1); // Magic number for verification
353 sbuf->reserveInt32(1); // Version number
354 sbuf->reserveInteger(1); // For m_base_data_type
355 sbuf->reserveInt64(1); // For m_memory_size
356 sbuf->reserveInteger(1); // For m_nb_dimension
357 sbuf->reserveInt64(1); // For m_nb_element
358 sbuf->reserveInt64(1); // For m_nb_base_element
359 sbuf->reserveInteger(1); // For m_is_multi_size
360 sbuf->reserveInt64(1); // For m_element_size
361
362 sbuf->reserveInt64(1); // For m_extents.size()
363 sbuf->reserveSpan(eBasicDataType::Int64, m_extents.size()); // For the dimensions
364
365 sbuf->reserveInt32(1); // For the number of values in 'm_shape'
366 sbuf->reserveSpan(eBasicDataType::Int32, m_shape.nbDimension()); // For 'm_shape' data
367
368 sbuf->reserveInt64(1); // For m_const_buffer.size()
369 sbuf->reserveSpan(eBasicDataType::Byte, m_const_buffer.size()); // For the data
370 break;
372 sbuf->putInt64(SERIALIZE_MAGIC_NUMBER); // Magic number for verification
373 sbuf->putInt32(1); // Version number
374 sbuf->putInteger(m_base_data_type); // For m_base_data_type
375 sbuf->putInt64(m_memory_size); // For m_memory_size
376 sbuf->putInteger(m_nb_dimension); // For m_nb_dimension
377 sbuf->putInt64(m_nb_element); // For m_nb_element
378 sbuf->putInt64(m_nb_base_element); // For m_nb_base_element
379 sbuf->putInteger(m_is_multi_size); // For m_is_multi_size
380 sbuf->putInt64(m_element_size); // For m_element_size
381
382 sbuf->putInt64(m_extents.size()); // For m_extents.size()
383 sbuf->putSpan(m_extents); // For the dimensions
384
385 sbuf->putInt32(m_shape.nbDimension()); // For m_shape.nbDimension()
386 sbuf->putSpan(m_shape.dimensions()); // For the dimensions
387
388 sbuf->putInt64(m_const_buffer.size()); // For m_const_buffer.size()
389 sbuf->putSpan(m_const_buffer); // For the data
390 break;
392 ARCANE_THROW(NotSupportedException, "ModeGet in const method");
393 }
394}
395
396/*---------------------------------------------------------------------------*/
397/*---------------------------------------------------------------------------*/
398
399extern "C++" ARCANE_CORE_EXPORT
402 Integer nb_dim, Int64 nb_element, Int64 nb_base_element,
403 bool is_multi_size, Int64ConstArrayView dimensions, const ArrayShape& shape)
404{
405 return createRef<SerializedData>(data_type, memory_size, nb_dim, nb_element,
406 nb_base_element, is_multi_size, dimensions, shape);
407}
408
409/*---------------------------------------------------------------------------*/
410/*---------------------------------------------------------------------------*/
411
412extern "C++" ARCANE_CORE_EXPORT
413Ref<ISerializedData>
415 Integer nb_dim, Int64 nb_element, Int64 nb_base_element,
416 bool is_multi_size, Int64ConstArrayView dimensions)
417{
418 return arcaneCreateSerializedDataRef(data_type, memory_size, nb_dim, nb_element,
419 nb_base_element, is_multi_size, dimensions, ArrayShape());
420}
421
422/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
425extern "C++" ARCANE_CORE_EXPORT
426Ref<ISerializedData>
431
432/*---------------------------------------------------------------------------*/
433/*---------------------------------------------------------------------------*/
434
435} // End namespace Arcane
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro to define methods managing counters of references.
Integer size() const
Number of elements in the vector.
Array shape.
Definition ArrayShape.h:42
Int32 nbDimension() const
Rank of the shape.
Definition ArrayShape.h:53
SmallSpan< const Int32 > dimensions() const
Values of each dimension.
Definition ArrayShape.h:56
void setDimensions(Span< const Int32 > dims)
Sets the number and values of the dimensions.
Definition ArrayShape.cc:64
void resize(Int64 s)
Changes the number of elements in the array to s.
Interface of a hashing algorithm.
virtual void computeHash64(Span< const Byte > input, ByteArray &output)
Calculates the hash value for the array input.
virtual Integer getInteger()=0
Retrieve a size.
virtual Int64 getInt64()=0
Retrieve a size.
virtual eReadMode readMode() const =0
Read mode.
virtual eMode mode() const =0
Current operating mode.
@ ReadReplace
Replace current elements with those read.
@ ReadAdd
Add those read to the current elements.
virtual void getSpan(Span< Real > values)
Retrieve the array values.
virtual Int32 getInt32()=0
Retrieve an integer.
Reference to an instance.
Thread-safe implementation of a reference counter.
void serialize(ISerializer *buffer) override
Serialize the data for reading or writing.
void computeHash(IHashAlgorithm *algo, ByteArray &output) const override
Compute a hash key on this data.
Int64ConstArrayView extents() const override
Array containing the number of elements for each dimension.
Span< Byte > writableBytes() override
View of the serialized values.
void setConstBytes(Span< const Byte > bytes) override
Positions the serialized values for reading.
void allocateMemory(Int64 size) override
Allocates an array to hold the serialized elements.
Integer nbDimension() const override
Dimension. 0 for a scalar, 1 for a 1D array, ...
Span< const Byte > constBytes() const override
Serialized values.
Int64 nbBaseElement() const override
Number of base elements.
void setBytes(Span< Byte > bytes) override
Positions the serialized values.
Span< Byte > bytes() override
Serialized values.
eDataType baseDataType() const override
Data type.
bool isMultiSize() const override
Indicates if it is a multi-size array. (only relevant if nbDimension()>1).
void setWritableBytes(Span< Byte > bytes) override
Positions the serialized values.
Int64 memorySize() const override
Indicates the number of bytes that must be allocated to store or read the data.
void setBytes(Span< const Byte > bytes) override
Positions the serialized values.
void setBuffer(ByteArrayView buffer) override
Positions the serialized values.
Int64 nbElement() const override
Number of elements.
Span< const Byte > bytes() const override
Serialized values.
ArrayShape shape() const override
Shape of the array associated with the data.
View of an array of elements of type T.
Definition Span.h:635
1D data vector with value semantics (STL style).
constexpr view_type smallView()
Constant view of this view.
Definition Span.h:392
constexpr ConstArrayView< value_type > constSmallView() const
Constant view of this view.
Definition Span.h:401
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:327
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
ARCANE_DATATYPE_EXPORT Integer dataTypeSize(eDataType type)
Size of data type type (which must be different from DT_String).
Definition DataTypes.cc:111
Ref< ISerializedData > arcaneCreateSerializedDataRef(eDataType data_type, Int64 memory_size, Integer nb_dim, Int64 nb_element, Int64 nb_base_element, bool is_multi_size, Int64ConstArrayView dimensions)
Creates serialized data.
Ref< TrueType > createRef(Args &&... args)
Creates an instance of type TrueType with arguments Args and returns a reference to it.
ArrayView< Byte > ByteArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:447
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:121
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
Ref< ISerializedData > arcaneCreateEmptySerializedDataRef()
Creates serialized data.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
eDataType
Data type.
Definition DataTypes.h:41
@ DT_Unknown
Unknown or uninitialized data type.
Definition DataTypes.h:58
std::int32_t Int32
Signed integer type of 32 bits.