COROIO: coroio/actors/messages.hpp Source File
COROIO
Loading...
Searching...
No Matches
messages.hpp
1#pragma once
2
3#include <memory>
4#include <sstream>
5#include <cstring>
6#include <type_traits>
7
8namespace NNet {
9namespace NActors {
10
11struct TBlob {
12 using TRawPtr = std::shared_ptr<void>;
13 TRawPtr Data = nullptr;
14 uint32_t Size = 0;
15 enum class PointerType {
16 Near, // Pointer to the object (for actor communication)
17 Far // Serialized representation (for network transmission)
18 } Type;
19};
20
21template<typename T>
22constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
23
24template<typename T, typename = void>
25struct has_data_members : std::true_type {};
26
27template<typename T>
28struct has_data_members<T, std::enable_if_t<
29 std::is_empty_v<T> &&
30 std::is_trivial_v<T> &&
31 std::is_standard_layout_v<T>
32>> : std::false_type {};
33
34template<typename T>
35constexpr bool has_data_members_v = has_data_members<T>::value;
36
37template<typename T>
38constexpr size_t sizeof_data() {
39 if constexpr (has_data_members_v<T>) {
40 return sizeof(T);
41 } else {
42 return 0;
43 }
44}
45
46template<typename T, typename TAllocator>
47typename std::enable_if_t<is_pod_v<T>, TBlob>
48SerializePodNear(T&& message, TAllocator& alloc)
49{
50 constexpr uint32_t size = sizeof_data<T>();
51
52 TBlob::TRawPtr rawPtr = nullptr;
53
54 if constexpr (size > 0) {
55 auto* data = alloc.Acquire(size);
56 new (data) T(std::move(message));
57
58 rawPtr = TBlob::TRawPtr(data, [&alloc](void* ptr) {
59 alloc.Release(ptr);
60 });
61 }
62
63 return TBlob{std::move(rawPtr), size, TBlob::PointerType::Near};
64}
65
66template<typename T, typename TAllocator>
67typename std::enable_if_t<!is_pod_v<T>, TBlob>
68SerializeNonPodNear(T&& message, TAllocator& alloc)
69{
70 T* obj = new T(std::forward<T>(message));
71
72 auto rawPtr = TBlob::TRawPtr(obj, [](void* ptr) {
73 delete reinterpret_cast<T*>(ptr);
74 });
75
76 return TBlob{std::move(rawPtr), sizeof(T), TBlob::PointerType::Near};
77}
78
79template<typename T, typename TAllocator>
80TBlob SerializeNear(T&& message, TAllocator& alloc)
81{
82 if constexpr (is_pod_v<T>) {
83 return SerializePodNear<T>(std::forward<T>(message), alloc);
84 } else {
85 return SerializeNonPodNear<T>(std::forward<T>(message), alloc);
86 }
87}
88
89template<typename T>
90void SerializeToStream(const T& obj, std::ostringstream& oss)
91{
92 static_assert(sizeof(T) == 0, "Serialization not implemented for this type");
93}
94
95template<typename T>
96TBlob SerializeFar(TBlob blob)
97{
98 if constexpr (is_pod_v<T>) {
99 blob.Type = TBlob::PointerType::Far;
100 return blob; // For POD, far == near, just share the pointer
101 } else {
102 T* obj = reinterpret_cast<T*>(blob.Data.get());
103 std::ostringstream oss;
104 SerializeToStream(*obj, oss);
105 void* data = ::operator new(oss.str().size());
106 std::memcpy(data, oss.str().data(), oss.str().size());
107 auto rawPtr = TBlob::TRawPtr(data, [](void* ptr) {
108 ::operator delete(ptr);
109 });
110 return TBlob{std::move(rawPtr), static_cast<uint32_t>(oss.str().size()), TBlob::PointerType::Far};
111 }
112}
113
114template<typename T>
115auto DeserializeNear(const TBlob& blob) -> std::conditional_t<sizeof_data<T>() == 0, T, T&> {
116 if constexpr (sizeof_data<T>() == 0) {
117 return T{};
118 } else {
119 return *reinterpret_cast<T*>(blob.Data.get());
120 }
121}
122
123template<typename T>
124void DeserializeFromStream(T& obj, std::istringstream& iss) {
125 static_assert(sizeof(T) == 0, "Deserialization not implemented for this type");
126}
127
128template<typename T>
129auto DeserializeFar(const TBlob& blob) -> std::conditional_t<is_pod_v<T> && (sizeof_data<T>()>0), T&, T> {
130 if constexpr (is_pod_v<T>) {
131 return DeserializeNear<T>(blob);
132 } else {
133 std::istringstream iss(std::string(reinterpret_cast<const char*>(blob.Data.get()), blob.Size));
134 T obj;
135 DeserializeFromStream(obj, iss);
136 return obj;
137 }
138}
139
140} // namespace NActors
141} // namespace NNet
Definition messages.hpp:11
Definition messages.hpp:25