data_descriptor.h
Go to the documentation of this file.
1 #ifndef TTG_SERIALIZATION_DATA_DESCRIPTOR_H
2 #define TTG_SERIALIZATION_DATA_DESCRIPTOR_H
3 
4 #include <cstdint>
5 
6 #ifdef TTG_SERIALIZATION_SUPPORTS_MADNESS
7 #include <madness/world/buffer_archive.h>
8 #endif
9 
11 
13 
14 #include <cstring> // for std::memcpy
15 
17 
22 extern "C" struct ttg_data_descriptor {
23  const char *name;
24 
28  uint64_t (*payload_size)(const void *object);
29 
36  uint64_t (*pack_payload)(const void *object, uint64_t max_nbytes_to_write, uint64_t offset, void *buf);
37 
44  uint64_t (*unpack_payload)(void *object, uint64_t max_nbytes_to_read, uint64_t offset, const void *buf);
45 
46  void (*print)(const void *object);
47 };
48 
49 namespace ttg {
50 
59  template <typename T, typename Enabler = void>
61 
64  template <typename T>
66  T, std::enable_if_t<detail::is_memcpyable_v<T> && !detail::is_user_buffer_serializable_v<T> &&
67  !ttg::has_split_metadata<T>::value>> {
68  static constexpr const bool serialize_size_is_const = true;
69 
73  static uint64_t payload_size(const void *object) { return static_cast<uint64_t>(sizeof(T)); }
74 
81  static uint64_t pack_payload(const void *object, uint64_t max_nbytes_to_write, uint64_t begin, void *buf) {
82  unsigned char *char_buf = reinterpret_cast<unsigned char *>(buf);
83  assert(sizeof(T)<=max_nbytes_to_write);
84  std::memcpy(&char_buf[begin], object, sizeof(T));
85  return begin + sizeof(T);
86  }
87 
94  static uint64_t unpack_payload(void *object, uint64_t max_nbytes_to_read, uint64_t begin, const void *buf) {
95  const unsigned char *char_buf = reinterpret_cast<const unsigned char *>(buf);
96  assert(sizeof(T)<=max_nbytes_to_read);
97  std::memcpy(object, &char_buf[begin], sizeof(T));
98  return begin + sizeof(T);
99  }
100  };
101 
104  template <typename T>
105  struct default_data_descriptor<T, std::enable_if_t<ttg::has_split_metadata<T>::value>> {
106  static constexpr const bool serialize_size_is_const = false;
107 
111  static uint64_t payload_size(const void *object) {
113  const T *t = reinterpret_cast<T *>(object);
114  auto metadata = smd.get_metadata(t);
115  size_t size = sizeof(metadata);
116  for (auto &&iovec : smd.get_data(t)) {
117  size += iovec.num_bytes;
118  }
119 
120  return static_cast<uint64_t>(size);
121  }
122 
129  static uint64_t pack_payload(const void *object, uint64_t max_nbytes_to_write, uint64_t begin, void *buf) {
131  const T *t = reinterpret_cast<T *>(object);
132 
133  unsigned char *char_buf = reinterpret_cast<unsigned char *>(buf);
134  auto metadata = smd.get_metadata(t);
135  assert(sizeof(metadata) <= max_nbytes_to_write);
136  std::memcpy(&char_buf[begin], metadata, sizeof(metadata));
137  size_t pos = sizeof(metadata);
138  for (auto &&iovec : smd.get_data(t)) {
139  std::memcpy(&char_buf[begin + pos], iovec.data, iovec.num_bytes);
140  pos += iovec.num_bytes;
141  assert(pos <= max_nbytes_to_write);
142  }
143  return begin + pos;
144  }
145 
152  static uint64_t unpack_payload(void *object, uint64_t max_nbytes_to_read, uint64_t begin, const void *buf) {
154  T *t = reinterpret_cast<T *>(object);
155 
156  using metadata_t = decltype(smd.get_metadata(t));
157  assert(sizeof(metadata_t) <= max_nbytes_to_read);
158  const unsigned char *char_buf = reinterpret_cast<const unsigned char *>(buf);
159  const metadata_t *metadata = reinterpret_cast<const metadata_t *>(char_buf + begin);
160  T t_created = smd.create_from_metadata();
161  size_t pos = sizeof(metadata);
162  *t = t_created;
163  for (auto &&iovec : smd.get_data(t)) {
164  std::memcpy(iovec.data, &char_buf[begin + pos], iovec.num_bytes);
165  pos += iovec.num_bytes;
166  assert(pos <= max_nbytes_to_read);
167  }
168  return begin + pos;
169  }
170  };
171 
172 } // namespace ttg
173 
174 #if defined(TTG_SERIALIZATION_SUPPORTS_MADNESS)
175 
176 namespace ttg {
177 
179  template <typename T>
180  struct default_data_descriptor<
181  T, std::enable_if_t<((!detail::is_memcpyable_v<T> && detail::is_madness_buffer_serializable_v<T>) ||
182  detail::is_madness_user_buffer_serializable_v<T>)&&!ttg::has_split_metadata<T>::value>> {
183  static constexpr const bool serialize_size_is_const = false;
184 
188  static uint64_t payload_size(const void *object) {
189  madness::archive::BufferOutputArchive ar;
190  ar & (*static_cast<std::add_pointer_t<std::add_const_t<T>>>(object));
191  return static_cast<uint64_t>(ar.size());
192  }
193 
200  static uint64_t pack_payload(const void *object, uint64_t max_nbytes_to_write, uint64_t pos, void *_buf) {
201  unsigned char *buf = reinterpret_cast<unsigned char *>(_buf);
202  madness::archive::BufferOutputArchive ar(&buf[pos], max_nbytes_to_write);
203  ar & (*static_cast<std::add_pointer_t<std::add_const_t<T>>>(object));
204  return pos + ar.size();
205  }
206 
213  static uint64_t unpack_payload(void *object, uint64_t max_nbytes_to_read, uint64_t pos, const void *_buf) {
214  const unsigned char *buf = reinterpret_cast<const unsigned char *>(_buf);
215  madness::archive::BufferInputArchive ar(&buf[pos], max_nbytes_to_read);
216  ar & (*static_cast<std::add_pointer_t<T>>(object));
217  return pos + (max_nbytes_to_read - ar.nbyte_avail());
218  }
219  };
220 
221 } // namespace ttg
222 
223 #endif // has MADNESS serialization
224 
225 #if defined(TTG_SERIALIZATION_SUPPORTS_BOOST)
226 
228 
229 namespace ttg {
230 
232  template <typename T>
233  struct default_data_descriptor<
234  T, std::enable_if_t<(!detail::is_memcpyable_v<T> && !detail::is_madness_buffer_serializable_v<T> &&
235  detail::is_boost_buffer_serializable_v<T>) ||
236  (!detail::is_madness_user_buffer_serializable_v<T> &&
237  detail::is_boost_user_buffer_serializable_v<T>)>> {
238  static constexpr const bool serialize_size_is_const = false;
239 
243  static uint64_t payload_size(const void *object) {
245  oa << (*static_cast<std::add_pointer_t<std::add_const_t<T>>>(object));
246  return oa.streambuf().size();
247  }
248 
255  static uint64_t pack_payload(const void *object, uint64_t max_nbytes_to_write, uint64_t pos, void *buf) {
256  auto oa = ttg::detail::make_boost_buffer_oarchive(buf, pos + max_nbytes_to_write, pos);
257  oa << (*static_cast<std::add_pointer_t<std::add_const_t<T>>>(object));
258  assert(oa.streambuf().size() <= max_nbytes_to_write);
259  return pos + oa.streambuf().size();
260  }
261 
268  static uint64_t unpack_payload(void *object, uint64_t max_nbytes_to_read, uint64_t pos, const void *buf) {
269  auto ia = ttg::detail::make_boost_buffer_iarchive(buf, pos + max_nbytes_to_read, pos);
270  ia >> (*static_cast<std::add_pointer_t<T>>(object));
271  assert(ia.streambuf().size() <= max_nbytes_to_read);
272  return pos + ia.streambuf().size();
273  }
274  };
275 
276 } // namespace ttg
277 
278 #endif // has Boost serialization
279 
280 namespace ttg {
281 
282  // Returns a pointer to a constant static instance initialized
283  // once at run time.
284  template <typename T>
286  static const ttg_data_descriptor d = {
289  return &d;
290  }
291 
292 } // namespace ttg
293 
294 #endif // TTG_SERIALIZATION_DATA_DESCRIPTOR_H
optimized data-only serializer
Definition: archive.h:94
auto make_boost_buffer_iarchive(const void *const buf, std::size_t size, std::size_t buf_offset=0)
constructs a boost_buffer_iarchive object
Definition: archive.h:390
auto make_boost_buffer_oarchive(void *const buf, std::size_t size, std::size_t buf_offset=0)
constructs a boost_buffer_oarchive object
Definition: archive.h:230
top-level TTG namespace contains runtime-neutral functionality
Definition: keymap.h:8
int size(World world=default_execution_context())
Definition: run.h:89
const ttg_data_descriptor * get_data_descriptor()
static uint64_t unpack_payload(void *object, uint64_t max_nbytes_to_read, uint64_t begin, const void *buf)
deserializes object from a buffer
static uint64_t pack_payload(const void *object, uint64_t max_nbytes_to_write, uint64_t begin, void *buf)
serializes object to a buffer
static uint64_t unpack_payload(void *object, uint64_t max_nbytes_to_read, uint64_t begin, const void *buf)
deserializes object from a buffer
static uint64_t pack_payload(const void *object, uint64_t max_nbytes_to_write, uint64_t begin, void *buf)
serializes object to a buffer
static uint64_t payload_size(const void *object)
measures the size of the binary representation of object
Provides (de)serialization of C++ data that can be invoked from C via ttg_data_descriptor.
std::size_t num_bytes
The number of bytes to read from / write to the memory location given by data.
Definition: iovec.h:13
void * data
Pointer to the data to be read from / written to.
Definition: iovec.h:15
uint64_t(* pack_payload)(const void *object, uint64_t max_nbytes_to_write, uint64_t offset, void *buf)
serializes object to a buffer
uint64_t(* payload_size)(const void *object)
measures the size of the binary representation of object
uint64_t(* unpack_payload)(void *object, uint64_t max_nbytes_to_read, uint64_t offset, const void *buf)
deserializes object from a buffer
void(* print)(const void *object)