You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Developer/Serialization.md
+83-70Lines changed: 83 additions & 70 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,39 +2,35 @@
2
2
3
3
This guide explains how to implement serialization using the Cereal library within Graphitti. If you're looking to add serialization to your class, follow this guide. For more comprehensive information on Cereal, refer to their [official documentation](https://uscilab.github.io/cereal/index.html).
4
4
5
-
<details>
6
-
<summary><strong>
5
+
<strong>
7
6
Understanding Serialization and Deserialization
8
-
</strong></summary>
7
+
</strong>
9
8
10
9
Serialization involves converting an object or data structure into a format that can be stored or transmitted, while deserialization is the reverse process— reconstructing an object from the serialized format.
11
-
</details>
12
10
<br>
13
-
<details>
14
-
<summary><strong>
11
+
12
+
<strong>
15
13
What is Cereal?
16
-
</strong></summary>
14
+
</strong>
17
15
18
16
Cereal is a lightweight C++11 library designed for object serialization and deserialization. It provides a straightforward interface for serializing objects and supports a wide range of data types. Cereal is efficient and well-suited for handling large data sets, making it a preferred choice for serialization tasks in Graphitti.
19
-
</details>
20
17
<br>
21
18
22
-
<details>
23
-
<summary><strong>
19
+
20
+
<strong>
24
21
Why Graphitti Uses Serialization?
25
-
</strong></summary>
22
+
</strong>
26
23
27
24
Graphitti utilizes Cereal to enable efficient serialization and deserialization of the network structure. Serialized data can serve as a checkpoint for large simulations or as input for subsequent simulations with varying conditions. This flexibility enhances Graphitti's efficiency and adaptability in modeling scenarios.
28
-
</details>
29
25
<br>
30
26
31
-
## Basics of Cereal
27
+
## Understand Cereal at a High Level
32
28
33
29
### C++ Features Supported by Cereal
34
30
35
-
-**Standard Library Support**: Cereal fully supports the C++11 [standard library](http://en.cppreference.com/w/). You can include the necessary headers from Cereal to enable support for various types (e.g., `<cereal/types/vector.hpp>`). Refer to the [Cereal Doxygen docs](https://uscilab.github.io/cereal/assets/doxygen/group__STLSupport.html) for a complete list of supported types.
31
+
-**Standard Library Support**: Cereal fully supports the C++11 [standard library](http://en.cppreference.com/w/). You can include the necessary headers from Cereal to enable support for various types (e.g., If you need to serialize a `std::vector`, add `<cereal/types/vector.hpp>`). Refer to the complete list of supported types below or in [Cereal Doxygen docs](https://uscilab.github.io/cereal/assets/doxygen/group__STLSupport.html).
36
32
37
-
-**Smart Pointers**: Cereal supports modern smart pointers (`std::shared_ptr` and `std::unique_ptr`) via `<cereal/types/memory.hpp>`. However, raw pointers or references are not supported.
33
+
-**Smart Pointers**: Cereal supports modern smart pointers (`std::shared_ptr` and `std::unique_ptr`) via `<cereal/types/memory.hpp>`. <strong> However, raw pointers or references are NOT supported.</strong>
38
34
39
35
-**Inheritance and Polymorphism**: Cereal can seamlessly handles inheritance and polymorphism- more on this in the coming section.
40
36
@@ -50,25 +46,30 @@ Graphitti utilizes Cereal to enable efficient serialization and deserialization
50
46
51
47
-**Defining Serialization Functions**: Cereal requires to know which data members to serialize in a class. By implementing a serialization function `serialize` within a class, you indicate to Cereal which data members should be serialized.
52
48
53
-
-**Default Constructor Requirement**:Cereal requires access to a default constructor for classes it serializes to construct the object during deserialization.
49
+
-**Default Constructor Requirement**:Cereal requires access to a default constructor for classes it serializes to construct the object during deserialization.
54
50
55
51
-**Name-Value Pairs**: Cereal supports name-value pairs, allowing you to attach names to serialized objects. This feature is particularly useful for XML archives and is adopted in Graphitti's serialization process.
56
52
57
53
-**Class Versioning**: While still in work in progress in Graphitti, Cereal supports class versioning, enabling compatibility between different versions of serialized objects.
58
54
59
55
## Incorporate Cereal in your class
60
56
61
-
- Cereal supports two approaches for serialization functions: internal or external. Cereal also provides two types of serialization function `serialize` and `load and save`. For consistency within Graphitti, it's recommended to use an internal single `serialize` function.
62
-
57
+
- Cereal supports two approaches for serialization functions: internal or external. Cereal also provides two types of serialization function `serialize` and `load and save`. For consistency within Graphitti, use an internal single `serialize` function.
63
58
- Throughout Graphitti, we typically serialize all data members (private, protected, and public) of a class.
64
-
<br>
65
59
66
-
### **Step 01: Include Necessary Cereal Headers**
67
-
Include the necessary Cereal headers for the data member types you want to serialize. If you are using a custom data member type, follow these steps for the custom data type class or struct as well.
60
+
### **STEP 01: ADD CEREAL HEADERS**
61
+
Before implementing serialization in your class, you need to include the appropriate Cereal headers for the types of data members you want to serialize. Cereal provides headers for various standard types, such as vectors, strings, and other containers.
62
+
63
+
- For example, if you're serializing a `std::vector<int>`, you'll need to include the following header:
64
+
```cpp
65
+
#include<cereal/types/vector.hpp>
66
+
```
67
+
68
+
- If you are using custom types, ensure the serialization process is correctly implemented for those types as well. The same approach applies to user-defined types, so include the appropriate headers and define the serialize function in that class or struct.
68
69
69
70
<details>
70
71
71
-
<summary>Refer to the table below for a reference on commonly used C++ data types and their corresponding Cereal headers</summary>
72
+
<summary><strong>Commonly used C++ data types and their corresponding Cereal headers</strong></summary>
72
73
73
74
74
75
| Type | Header to include |
@@ -101,11 +102,27 @@ Graphitti utilizes Cereal to enable efficient serialization and deserialization
101
102
102
103
<br>
103
104
104
-
### **Step 02: Include and Define the Serialize Function**
105
+
### **STEP 02: ADD SERIALIZE FUNCTION**
105
106
106
107
Within your class header file
107
-
1. Declare the `serialize` function under the public section.
108
-
2. At the end of your header file, define the `serialize` function for your class.
108
+
- Firstly, declare the `serialize` function inside the class:
109
+
- Add the following template function signature in the public section of your class to allow serialization for any archive type.
110
+
```cpp
111
+
template <classArchive>
112
+
voidserialize(Archive & archive);
113
+
```
114
+
- Secondly, define the `serialize` function outside the class:
115
+
- After your class declaration, define the serialize function at the end of the header file.
116
+
- This function specifies which member variables are serialized and deserialized, and how that process occurs.
117
+
```cpp
118
+
template <class Archive>
119
+
void YOUR_CLASS_NAME::serialize(Archive &archive)
120
+
{
121
+
archive(ADD_YOUR_MEMBER_VARIABLES_HERE);
122
+
// Refer to the example below
123
+
}
124
+
```
125
+
Here’s a sample implementation to guide you:
109
126
110
127
```cpp
111
128
@@ -125,37 +142,40 @@ class MyCoolClass
125
142
int X_;
126
143
};
127
144
128
-
//STEP 02 (b): Define the serialize function at the bottom of the header file
145
+
//STEP 02 (b): Define the serialize function outside the class
Adjust the function names and data member names as per your specific requirements.
139
157
140
-
### **Step 03: Check for any Special Modifications**
158
+
NOTE:
159
+
- The `template <class Archive>` declaration allows the function to work with any type of Cereal archive (e.g., JSON, XML, binary).
160
+
- When defining the `serialize` function, use Cereal’s `make_nvp()` for custom names or `CEREAL_NVP()` for automatic name-value pair serialization.
161
+
- Defining the function outside the class maintains a consistent style for serialized code and makes the function easier to locate, especially in larger projects like Graphitti. This approach also keeps your class declaration cleaner and less cluttered.
141
162
142
-
If you answer "yes" to any of the following questions, follow the corresponding steps. Some classes may fall under multiple categories, so review all questions carefully.
163
+
### **STEP 03: SPECIAL CASES**
143
164
144
-
<details>
145
-
<summary><strong>
146
-
Is your class a derived class?
147
-
</summary></strong>
165
+
Cereal requires additional steps for certain special cases such as inheritance, polymorphism, and templates. In this section, we outline specific steps based on whether your class matches one of these conditions. If you answer "yes" to any of the following questions, follow the corresponding steps. Some classes may fall under multiple categories, so be sure to review all the details carefully.
148
166
149
-
Cereal needs a serialization path from the derived class to the base type(s). This is usually handled with either `cereal::base_class` or `cereal::virtual_base_class`.
167
+
### **1. DERIVED CLASS?**
168
+
This step explains how to serialize base classes in a derived class. Cereal requires a path from the derived to the base type(s), typically done with `cereal::base_class` or `cereal::virtual_base_class`.
150
169
151
-
#### [a] Is your class derived from a virtual inheritance ?
152
-
When inheriting from objects from a virtual inheritance (e.g.`class Derived : virtual Base`), the recommended method is to utilize `cereal::virtual_base_class<BaseT>(this)` to cast the derived class to the base class.
If your derived class uses virtual inheritance (`class Derived : virtual Base`), use `cereal::virtual_base_class<BaseT>(this)` to cast the derived class to its base class. Ensure this is placed at the start of the `archive` in the `serialize` function before member variables in the derived class.
153
173
154
174
```cpp
155
175
156
176
class MyDerived : virtual MyBase
157
177
{
158
-
int y;
178
+
int X_;
159
179
template <class Archive>
160
180
void serialize( Archive & ar );
161
181
};
@@ -164,20 +184,23 @@ template <class Archive>
164
184
void MyDerived::serialize( Archive & archive )
165
185
{
166
186
// We pass this cast to the base type for each base type we need to serialize.
#### [b] Is your class derived from a normal (non-virtual) inheritance ?
174
-
When inheriting from objects without using virtual inheritance (e.g.`class Derived : public Base`), the recommended method is to utilize `cereal::base_class<BaseT>(this)` to cast the derived class to the base class.
193
+
</details>
194
+
195
+
<details>
196
+
<summary><strong> Normal Inheritance ?</summary></strong>
197
+
For non-virtual inheritance (`class Derived : public Base`), use `cereal::base_class<BaseT>(this) to serialize the base class. Ensure this is placed at the start of the `archive` in the `serialize` function before member variables in the derived class.
175
198
176
199
```cpp
177
200
178
201
classMyDerived : publicMyBase
179
202
{
180
-
int y;
203
+
int X_;
181
204
template <classArchive>
182
205
void serialize( Archive & ar );
183
206
};
@@ -186,32 +209,33 @@ template <class Archive>
186
209
voidMyDerived::serialize( Archive & archive )
187
210
{
188
211
// We pass this cast to the base type for each base type we need to serialize.
For more details, refer to the official Cereal documentation on [inheritance](https://uscilab.github.io/cereal/inheritance.html)
196
219
197
220
</details>
198
-
<br>
199
221
200
-
<details>
201
-
<summary><strong>
202
-
Does your class exhibit polymorphic behavior?
203
-
</summary></strong>
222
+
### **2. EXHIBIT POLYMORPHISM?**
204
223
205
224
If you answered "yes" to the previous question about your class being a derived class, this is likely "yes" as well.
206
225
207
-
If your class exhibits polymorphic behavior, particularly if it's a derived class, follow these steps:
226
+
<details>
227
+
<summary><strong>
228
+
Follow these steps if your class exhibits polymorphic behavior:
229
+
</summary></strong>
208
230
209
231
1. Include Necessary Headers:
210
-
Make sure to include the polymorphic header to enable support for polymorphism in Cereal.
232
+
233
+
Make sure to include the polymorphic header to enable support for polymorphism in Cereal in the derived class.
211
234
``` #include <cereal/types/polymorphic.hpp> ```
212
235
213
236
2. Register Your Derived Types:
214
-
Register each derived class using `CEREAL_REGISTER_TYPE(DerivedClassName)`.
237
+
238
+
Register each derived class above the definition of the `serialize` function using `CEREAL_REGISTER_TYPE(DerivedClassName)` in the respective derived class.
215
239
216
240
```cpp
217
241
// be sure to include support for polymorphism
@@ -235,7 +259,8 @@ template <class Archive>
235
259
```
236
260
237
261
3. Register Your Base Class (if not registered automatically):
238
-
Normally, registering base classes is handled automatically if you serialize a derived type with either `cereal::base_class` or `cereal::virtual_base_class`. However, in situations where neither of these is used, explicit registration is required using the `CEREAL_REGISTER_POLYMORPHIC_RELATION` macro.
262
+
263
+
Normally, registering base classes is handled automatically if you serialize a derived type with either `cereal::base_class` or `cereal::virtual_base_class`. However, in situations where neither of these is used, explicit registration is required using the `CEREAL_REGISTER_POLYMORPHIC_RELATION` macro in the derived class.
239
264
240
265
```cpp
241
266
structMyEmptyBase
@@ -266,14 +291,14 @@ template <class Archive>
266
291
For more detailed information and examples on polymorphism in Cereal, refer to the official documentation on [Polymorphism](https://uscilab.github.io/cereal/polymorphism.html).
267
292
268
293
</details>
269
-
<br>
270
294
295
+
### **3. TEMPLATE?**
271
296
<details>
272
297
<summary><strong>
273
-
Is your class a template?
298
+
Template involves inheritance?
274
299
</summary></strong>
275
300
276
-
Follow all the steps from Step 01 as if your class is a regular class. However, if the template involves inheritance, you might need to register all potential instantiations of the template during polymorphism handling.
301
+
Follow all the steps from STEP 01 as if your class is a regular class. However, if the template involves inheritance, you might need to register all potential instantiations of the template during polymorphism handling.
Are you serializing smart pointers to objects that do not have a default constructor?
320
-
</summary></strong>
340
+
### **4. NO DEFAULT CONSTRUCTOR?**
321
341
322
342
Cereal provides a special overload method to handle this situation. Refer to the [Cereal documentation](https://uscilab.github.io/cereal/pointers) for detailed information on this technique.
323
343
324
-
</details>
325
-
<br>
326
-
327
-
## Debugging Cereal Errors in Graphitti
344
+
## Common Cereal Errors
328
345
329
346
Encountering a Cereal error during compiling or running Graphitti? Here's a checklist to troubleshoot:
330
347
@@ -349,10 +366,6 @@ Encountering a Cereal error during compiling or running Graphitti? Here's a chec
349
366
350
367
With these checks, you should be able to diagnose and resolve common Cereal errors in Graphitti.
351
368
352
-
<!-- ## Serialization flow in Graphitti (For Debugging purposes) -->
353
-
354
-
355
-
356
369
---------
357
370
[<< Go back to the Developer Documentation page](index.md)
0 commit comments