Add some comments to SpanHelpers.Char IndexOf and LastIndexOf (#17447)
[platform/upstream/coreclr.git] / src / gc / gcevent_serializers.h
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.
4
5 #ifndef __GCEVENT_SERIALIZERS_H__
6 #define __GCEVENT_SERIALIZERS_H__
7
8 /*
9  * gcevent_serializers.h - Serialization traits and plumbing for
10  * serializing dynamic events.
11  *
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.
16  *
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.
20  *
21  * ## Serializing Types
22  *
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`.
27  * 
28  * If you attempt to serialize a type that does not implement this trait,
29  * you will receive an error message like this:
30  *
31  * bool gc_event::EventSerializationTraits<Head>::Serialize(const T&,uint8_t **)': attempting to reference a deleted function
32  * with
33  *  [
34  *      Head=<your type you tried to serialize>,
35  *      T=<your type you tried to serialize>
36  *  ] 
37  * 
38  * If you get this message, you will need to specialize `EventSerializationTraits`
39  * for the type you want to serialize.
40  */ 
41
42 #ifdef _MSC_VER
43 #define ByteSwap32 _byteswap_ulong
44 #define ByteSwap64 _byteswap_uint64
45 #else
46 #define ByteSwap32 __bulitin_bswap32
47 #define ByteSwap64 __builtin_bswap64
48 #endif // MSC_VER
49
50 namespace gc_event
51 {
52
53 /*
54  * `EventSerializatonTraits` is a trait implemented by types that
55  * can be serialized to the payload of a dynamic event.
56  */
57 template<class T>
58 struct EventSerializationTraits
59 {
60     /*
61      * Serializes the value `value` to the buffer `buffer`, incrementing
62      * the buffer double-pointer to point to the next byte to be written.
63      * 
64      * It is the responsibility of the caller to ensure that the buffer is
65      * large enough to accomodate the serialized form of T.
66      */
67     static void Serialize(const T& value, uint8_t** buffer) = delete;
68
69     /*
70      * Returns the size of the value `value` if it were to be serialized.
71      */
72     static size_t SerializedSize(const T& value) = delete;
73 };
74
75 /*
76  * EventSerializationTraits implementation for uint32_t. Other integral types
77  * can follow this pattern.
78  *
79  * The convention here is that integral types are always serialized as
80  * little-endian.
81  */
82 template<>
83 struct EventSerializationTraits<uint32_t>
84 {
85     static void Serialize(const uint32_t& value, uint8_t** buffer)
86     {
87 #if defined(BIGENDIAN)
88         **((uint32_t**)buffer) = ByteSwap32(value);
89 #else
90         **((uint32_t**)buffer) = value;
91 #endif // BIGENDIAN
92         *buffer += sizeof(uint32_t);
93     }
94
95     static size_t SerializedSize(const uint32_t& value)
96     {
97         return sizeof(uint32_t);
98     }
99 };
100
101 /*
102  * Helper routines for serializing lists of arguments.
103  */
104
105 /*
106  * Given a list of arguments , returns the total size of
107  * the buffer required to fully serialize the list of arguments.
108  */
109 template<class Head>
110 size_t SerializedSize(Head head)
111 {
112     return EventSerializationTraits<Head>::SerializedSize(head);
113 }
114
115 template<class Head, class... Tail>
116 size_t SerializedSize(Head head, Tail... tail)
117 {
118     return EventSerializationTraits<Head>::SerializedSize(head) + SerializedSize(tail...);
119 }
120
121 /*
122  * Given a list of arguments and a list of actual parameters, serialize
123  * the arguments into the buffer that's given to us.
124  */
125 template<class Head>
126 void Serialize(uint8_t** buf, Head head)
127 {
128     EventSerializationTraits<Head>::Serialize(head, buf);
129 }
130
131 template<class Head, class... Tail>
132 void Serialize(uint8_t** buf, Head head, Tail... tail)
133 {
134     EventSerializationTraits<Head>::Serialize(head, buf);
135     Serialize(buf, tail...);
136 }
137
138 } // namespace gc_event
139
140 #endif // __GCEVENT_SERIALIZERS_H__
141