22 void operator()(
void* ptr) {
23 Release(Context, ptr);
26 void (*Release)(
void*,
void*) =
nullptr;
27 void* Context =
nullptr;
30template<
typename TLambda>
33 std::is_empty_v<TLambda> ||
sizeof(TLambda) <=
sizeof(
void*),
34 "Lambda must be stateless or capture only one pointer-sized value");
38 static std::enable_if_t<std::is_empty_v<std::decay_t<F>>,
TContextDeleter>
40 auto func_ptr = +[](
void* ,
void* ptr) {
41 std::decay_t<F>{}(ptr);
47 static std::enable_if_t<!std::is_empty_v<std::decay_t<F>>,
TContextDeleter>
49 void* captured_ptr = ExtractCapturedPointer(lambda);
51 auto func_ptr = +[](
void* ctx,
void* ptr) {
52 using LambdaType = std::decay_t<F>;
53 alignas(LambdaType)
char buffer[
sizeof(LambdaType)];
54 *
reinterpret_cast<void**
>(buffer) = ctx;
55 auto* lambda_ptr =
reinterpret_cast<LambdaType*
>(buffer);
64 static void* ExtractCapturedPointer(
const F& lambda) {
65 return *
reinterpret_cast<void* const*
>(&lambda);
72 template<
typename TFunc>
77 void operator()(
void* ptr) {
85 using TRawPtr = std::unique_ptr<void, TBlobDeleter>;
89 enum class PointerType {
96constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
98template<
typename T,
typename =
void>
103 std::is_empty_v<T> &&
104 std::is_trivial_v<T> &&
105 std::is_standard_layout_v<T>
106>> : std::false_type {};
112constexpr size_t sizeof_data() {
113 if constexpr (has_data_members_v<T>) {
120template<
typename T,
typename TAllocator,
typename... Args>
121typename std::enable_if_t<is_pod_v<T>, TBlob>
122SerializePodNear(TAllocator& alloc, Args&&... args)
124 constexpr uint32_t size = sizeof_data<T>();
126 TBlob::TRawPtr rawPtr =
nullptr;
128 if constexpr (size > 0) {
129 auto* data = alloc.Acquire(size);
130 new (data) T(std::forward<Args>(args)...);
132 rawPtr = TBlob::TRawPtr(data, TBlobDeleter{[&alloc](
void* ptr) {
137 return TBlob{std::move(rawPtr), size, TBlob::PointerType::Near};
140template<
typename T,
typename TAllocator,
typename... Args>
141typename std::enable_if_t<!is_pod_v<T>, TBlob>
142SerializeNonPodNear(TAllocator& alloc, Args&&... args)
144 T* obj =
new T(std::forward<Args>(args)...);
146 auto rawPtr = TBlob::TRawPtr(obj, TBlobDeleter{[](
void* ptr) {
147 delete reinterpret_cast<T*
>(ptr);
150 return TBlob{std::move(rawPtr),
sizeof(T), TBlob::PointerType::Near};
153template<
typename T,
typename TAllocator,
typename... Args>
154TBlob SerializeNear(TAllocator& alloc, Args&&... args)
156 if constexpr (is_pod_v<T>) {
157 return SerializePodNear<T>(alloc, std::forward<Args>(args)...);
159 return SerializeNonPodNear<T>(alloc, std::forward<Args>(args)...);
164void SerializeToStream(
const T& obj, std::ostringstream& oss)
166 static_assert(
sizeof(T) == 0,
"Serialization not implemented for this type");
170TBlob SerializeFar(TBlob blob)
172 if constexpr (is_pod_v<T>) {
173 blob.Type = TBlob::PointerType::Far;
176 T* obj =
reinterpret_cast<T*
>(blob.Data.get());
177 std::ostringstream oss;
178 SerializeToStream(*obj, oss);
179 void* data = ::operator
new(oss.str().size());
180 std::memcpy(data, oss.str().data(), oss.str().size());
181 auto rawPtr = TBlob::TRawPtr(data, TBlobDeleter{[](
void* ptr) {
182 ::operator
delete(ptr);
184 return TBlob{std::move(rawPtr),
static_cast<uint32_t
>(oss.str().size()), TBlob::PointerType::Far};
188template<
typename T,
typename TStream,
typename... Args>
189void SerializeFarInplace(TStream& stream, TActorId sender, TActorId recipient, Args&&... args)
191 if constexpr (is_pod_v<T>) {
192 constexpr auto size = sizeof_data<T>() +
sizeof(THeader);
193 auto buf = stream.Acquire(size);
194 char* p =
static_cast<char*
>(buf.data());
195 new (p) THeader {sender, recipient, T::MessageId, sizeof_data<T>()};
196 p +=
sizeof(THeader);
197 new (p) T(std::forward<Args>(args)...);
206 std::ostringstream oss;
207 SerializeToStream(T(std::forward<Args>(args)...), oss);
208 auto size = oss.str().size() +
sizeof(THeader);
209 auto buf = stream.Acquire(size);
210 char* p =
static_cast<char*
>(buf.data());
211 new (p) THeader {sender, recipient, T::MessageId,
static_cast<uint32_t
>(oss.str().size())};
212 p +=
sizeof(THeader);
213 std::memcpy(p, oss.str().data(), oss.str().size());
219auto DeserializeNear(
const TBlob& blob) -> std::conditional_t<sizeof_data<T>() == 0, T, T&> {
220 if constexpr (sizeof_data<T>() == 0) {
223 return *
reinterpret_cast<T*
>(blob.Data.get());
228void DeserializeFromStream(T& obj, std::istringstream& iss) {
229 static_assert(
sizeof(T) == 0,
"Deserialization not implemented for this type");
233auto DeserializeFar(
const TBlob& blob) -> std::conditional_t<is_pod_v<T> && (sizeof_data<T>()>0), T&, T> {
234 if constexpr (is_pod_v<T>) {
235 return DeserializeNear<T>(blob);
237 std::istringstream iss(std::string(
reinterpret_cast<const char*
>(blob.Data.get()), blob.Size));
239 DeserializeFromStream(obj, iss);
Definition messages.hpp:69
Definition messages.hpp:84
Definition messages.hpp:14
Definition messages.hpp:31
Definition messages.hpp:99