Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
custom_serdez.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 Stanford University, NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// custom field serialization/deserialization for instance fields in Realm
19
20#ifndef REALM_CUSTOM_SERDEZ_H
21#define REALM_CUSTOM_SERDEZ_H
22
23#include "realm/serialize.h"
24
25#include <sys/types.h>
26
27namespace Realm {
28
29 // When Realm copies data between two instances, it is normally done by bit-wise copies
30 // of the data
31 // for each element. There are two cases where this is either inefficient or
32 // incorrect:
33 // 1) a complex field type might be compressible (e.g. have a large amount of "don't
34 // care" subfields),
35 // reducing the amount of network traffic required to move the instance (although with
36 // some increase in the CPU cost of moving it)
37 // 2) a field may actually just hold a pointer to some more dynamic data structure - in
38 // this case,
39 // an instance copy needs to be a deep copy of the logical contents of the field
40
41 // custom serdez objects are registered with the runtime at startup (for now) and
42 // associated with an ID
43 // that can be provided:
44 // a) in CopySrcDstField objects in a copy operation (if one is provided for a field on
45 // the source side,
46 // the corresponding dst field also must have a custom serdez - it doesn't technically
47 // need to be the same one, but there's very few cases where having them different
48 // makes any sense)
49 // b) in the deletion of an instance, allowing any data that was dynamically allocated
50 // during
51 // deserialization to be reclaimed
52
53 // for now, a custom serdez is defined in the form of a class that looks like this:
54 // (in the not-too-distant future, this will be replaced by a set of CodeDescriptor's)
55#ifdef NOT_REALLY_CODE
56 class CustomSerdezExample {
57 public:
58 typedef... FIELD_TYPE; // the "deserialized type" stored in the instance (e.g. Object
59 // * for a dynamic structure)
60
61 // computes the number of bytes needed for the serialization of 'val'
62 static size_t serialized_size(const FIELD_TYPE &val);
63
64 // serializes 'val' into the provided buffer - no size is provided (serialized_size
65 // will be called first),
66 // but the function should return the bytes used
67 static size_t serialize(const FIELD_TYPE &val, void *buffer);
68
69 // deserializes the provided buffer into 'val' - the existing contents of 'val' are
70 // overwritten, but
71 // will have already been "destroyed" if this copy is overwriting previously valid
72 // data - this call should return the number of bytes consumed - note that the size
73 // of the buffer is not supplied (this means the serialization format must have some
74 // internal way of knowing how much to read)
75 static size_t deserialize(FIELD_TYPE &val, const void *buffer);
76
77 // destroys the contents of a field
78 static void destroy(FIELD_TYPE &val);
79 };
80#endif
81 template <typename T>
83 public:
84 typedef T *FIELD_TYPE;
85 static const size_t MAX_SERIALIZED_SIZE = sizeof(T);
86
87 static size_t serialized_size(const FIELD_TYPE &val) { return sizeof(T); }
88
89 static size_t serialize(const FIELD_TYPE &val, void *buffer)
90 {
91 memcpy(buffer, val, sizeof(T));
92 return sizeof(T);
93 }
94
95 static size_t deserialize(FIELD_TYPE &val, const void *buffer)
96 {
97 val = new T;
98 memcpy(val, buffer, sizeof(T));
99 return sizeof(T);
100 }
101
102 static void destroy(FIELD_TYPE &val) { delete val; }
103 };
104
105 // as a useful example, here's a templated serdez that works for anything that supports
106 // Realm's serialization
107 // framework
108 template <typename T, size_t MAX_SER_SIZE = 4096>
110 public:
111 typedef T *FIELD_TYPE; // field holds a pointer to the object
112 static const size_t MAX_SERIALIZED_SIZE = MAX_SER_SIZE;
113
114 static size_t serialized_size(const FIELD_TYPE &val)
115 {
117 bool ok = (bcs << (*val));
118 assert(ok);
119 return bcs.bytes_used();
120 }
121
122 static size_t serialize(const FIELD_TYPE &val, void *buffer)
123 {
124 // fake a max size, but it can't wrap the pointer
125 size_t max_size = size_t(-1) - reinterpret_cast<size_t>(buffer);
126 Serialization::FixedBufferSerializer fbs(buffer, max_size);
127 bool ok = (fbs << *val);
128 assert(ok);
129 return max_size -
130 fbs.bytes_left(); // because we didn't really tell it how many bytes we had
131 }
132
133 static size_t deserialize(FIELD_TYPE &val, const void *buffer)
134 {
135 val = new T; // assumes existence of default constructor
136 // fake a max size, but it can't wrap the pointer
137 size_t max_size = size_t(-1) - reinterpret_cast<size_t>(buffer);
138 Serialization::FixedBufferDeserializer fbd(buffer, max_size);
139 bool ok = (fbd >> (*val));
140 assert(ok);
141 return max_size - fbd.bytes_left();
142 }
143
144 static void destroy(FIELD_TYPE &val) { delete val; }
145 };
146
147 // some template-based type-erasure stuff for registration for now
148 typedef int CustomSerdezID;
149
151 public:
154
155 template <class SERDEZ>
157
158 virtual ~CustomSerdezUntyped(void);
159
160 virtual CustomSerdezUntyped *clone(void) const = 0;
161
162 // each operator exists in two forms: single-element and strided-array-of-elements
163
164 // computes the number of bytes needed for the serialization of 'val'
165 virtual size_t serialized_size(const void *field_ptr) const = 0;
166 virtual size_t serialized_size(const void *field_ptr, ptrdiff_t stride,
167 size_t count) const = 0;
168
169 // serializes 'val' into the provided buffer - no size is provided (serialized_size
170 // will be called first),
171 // but the function should return the bytes used
172 virtual size_t serialize(const void *field_ptr, void *buffer) const = 0;
173 virtual size_t serialize(const void *field_ptr, ptrdiff_t stride, size_t count,
174 void *buffer) const = 0;
175
176 // deserializes the provided buffer into 'val' - the existing contents of 'val' are
177 // overwritten, but
178 // will have already been "destroyed" if this copy is overwriting previously valid
179 // data - this call should return the number of bytes consumed - note that the size
180 // of the buffer is not supplied (this means the serialization format must have some
181 // internal way of knowing how much to read)
182 virtual size_t deserialize(void *field_ptr, const void *buffer) const = 0;
183 virtual size_t deserialize(void *field_ptr, ptrdiff_t stride, size_t count,
184 const void *buffer) const = 0;
185
186 // destroys the contents of a field
187 virtual void destroy(void *field_ptr) const = 0;
188 virtual void destroy(void *field_ptr, ptrdiff_t stride, size_t count) const = 0;
189 };
190
191 template <typename T>
193
194}; // namespace Realm
195
196#include "realm/custom_serdez.inl"
197
198#endif // ifndef REALM_REDOP_H
Definition custom_serdez.h:150
size_t sizeof_field_type
Definition custom_serdez.h:152
virtual size_t serialize(const void *field_ptr, void *buffer) const =0
size_t max_serialized_size
Definition custom_serdez.h:153
virtual size_t deserialize(void *field_ptr, ptrdiff_t stride, size_t count, const void *buffer) const =0
virtual CustomSerdezUntyped * clone(void) const =0
virtual size_t serialized_size(const void *field_ptr) const =0
virtual size_t serialized_size(const void *field_ptr, ptrdiff_t stride, size_t count) const =0
static CustomSerdezUntyped * create_custom_serdez(void)
virtual ~CustomSerdezUntyped(void)
virtual size_t serialize(const void *field_ptr, ptrdiff_t stride, size_t count, void *buffer) const =0
virtual void destroy(void *field_ptr) const =0
virtual size_t deserialize(void *field_ptr, const void *buffer) const =0
virtual void destroy(void *field_ptr, ptrdiff_t stride, size_t count) const =0
Definition custom_serdez.h:192
Definition custom_serdez.h:82
static void destroy(FIELD_TYPE &val)
Definition custom_serdez.h:102
static size_t serialized_size(const FIELD_TYPE &val)
Definition custom_serdez.h:87
T * FIELD_TYPE
Definition custom_serdez.h:84
static size_t deserialize(FIELD_TYPE &val, const void *buffer)
Definition custom_serdez.h:95
static const size_t MAX_SERIALIZED_SIZE
Definition custom_serdez.h:85
static size_t serialize(const FIELD_TYPE &val, void *buffer)
Definition custom_serdez.h:89
Definition custom_serdez.h:109
static const size_t MAX_SERIALIZED_SIZE
Definition custom_serdez.h:112
static size_t deserialize(FIELD_TYPE &val, const void *buffer)
Definition custom_serdez.h:133
static size_t serialize(const FIELD_TYPE &val, void *buffer)
Definition custom_serdez.h:122
static size_t serialized_size(const FIELD_TYPE &val)
Definition custom_serdez.h:114
T * FIELD_TYPE
Definition custom_serdez.h:111
static void destroy(FIELD_TYPE &val)
Definition custom_serdez.h:144
Definition activemsg.h:38
int CustomSerdezID
Definition custom_serdez.h:148
bool serialize(S &serdez, const ByteArrayRef &a)
bool deserialize(S &serdez, ByteArray &a)