1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 #ifndef __GCEVENT_SERIALIZERS_H__
6 #define __GCEVENT_SERIALIZERS_H__
9 * gcevent_serializers.h - Serialization traits and plumbing for
10 * serializing dynamic events.
12 * Dynamic events are events that can be fired by the GC without prior
13 * knowledge of the EE. In order to accomplish this, the GC sends raw
14 * bytes to the EE using the `IGCToCLR::FireDynamicEvent` callback, which
15 * the EE will then fire as its own event.
17 * In order to keep the friction of adding new dynamic events low, this
18 * file defines a simple ETW-style binary serialization format that
19 * is efficient and easy to both serialize and deserialize.
21 * ## Serializing Types
23 * This file makes use of `EventSerializationTraits` to serialize
24 * types. A type can opt-in to serialization using the mechanisms
25 * in this file by specializing the `EventSerializationTraits` template,
26 * providing implementations of `Serialize` and `SerializedSize`.
28 * If you attempt to serialize a type that does not implement this trait,
29 * you will receive an error message like this:
31 * bool gc_event::EventSerializationTraits<Head>::Serialize(const T&,uint8_t **)': attempting to reference a deleted function
34 * Head=<your type you tried to serialize>,
35 * T=<your type you tried to serialize>
38 * If you get this message, you will need to specialize `EventSerializationTraits`
39 * for the type you want to serialize.
43 #define ByteSwap32 _byteswap_ulong
44 #define ByteSwap64 _byteswap_uint64
46 #define ByteSwap32 __bulitin_bswap32
47 #define ByteSwap64 __builtin_bswap64
54 * `EventSerializatonTraits` is a trait implemented by types that
55 * can be serialized to the payload of a dynamic event.
58 struct EventSerializationTraits
61 * Serializes the value `value` to the buffer `buffer`, incrementing
62 * the buffer double-pointer to point to the next byte to be written.
64 * It is the responsibility of the caller to ensure that the buffer is
65 * large enough to accomodate the serialized form of T.
67 static void Serialize(const T& value, uint8_t** buffer) = delete;
70 * Returns the size of the value `value` if it were to be serialized.
72 static size_t SerializedSize(const T& value) = delete;
76 * EventSerializationTraits implementation for uint32_t. Other integral types
77 * can follow this pattern.
79 * The convention here is that integral types are always serialized as
83 struct EventSerializationTraits<uint32_t>
85 static void Serialize(const uint32_t& value, uint8_t** buffer)
87 #if defined(BIGENDIAN)
88 **((uint32_t**)buffer) = ByteSwap32(value);
90 **((uint32_t**)buffer) = value;
92 *buffer += sizeof(uint32_t);
95 static size_t SerializedSize(const uint32_t& value)
97 return sizeof(uint32_t);
102 * Helper routines for serializing lists of arguments.
106 * Given a list of arguments , returns the total size of
107 * the buffer required to fully serialize the list of arguments.
110 size_t SerializedSize(Head head)
112 return EventSerializationTraits<Head>::SerializedSize(head);
115 template<class Head, class... Tail>
116 size_t SerializedSize(Head head, Tail... tail)
118 return EventSerializationTraits<Head>::SerializedSize(head) + SerializedSize(tail...);
122 * Given a list of arguments and a list of actual parameters, serialize
123 * the arguments into the buffer that's given to us.
126 void Serialize(uint8_t** buf, Head head)
128 EventSerializationTraits<Head>::Serialize(head, buf);
131 template<class Head, class... Tail>
132 void Serialize(uint8_t** buf, Head head, Tail... tail)
134 EventSerializationTraits<Head>::Serialize(head, buf);
135 Serialize(buf, tail...);
138 } // namespace gc_event
140 #endif // __GCEVENT_SERIALIZERS_H__