1 //===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
11 #define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
14 #include "llvm/Support/thread.h"
25 /// TypeNameSequence is a utility for rendering sequences of types to a string
26 /// by rendering each type, separated by ", ".
27 template <typename... ArgTs> class RPCTypeNameSequence {};
29 /// Render an empty TypeNameSequence to an ostream.
30 template <typename OStream>
31 OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
35 /// Render a TypeNameSequence of a single type to an ostream.
36 template <typename OStream, typename ArgT>
37 OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
38 OS << RPCTypeName<ArgT>::getName();
42 /// Render a TypeNameSequence of more than one type to an ostream.
43 template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
45 operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
46 OS << RPCTypeName<ArgT1>::getName() << ", "
47 << RPCTypeNameSequence<ArgT2, ArgTs...>();
52 class RPCTypeName<void> {
54 static const char* getName() { return "void"; }
58 class RPCTypeName<int8_t> {
60 static const char* getName() { return "int8_t"; }
64 class RPCTypeName<uint8_t> {
66 static const char* getName() { return "uint8_t"; }
70 class RPCTypeName<int16_t> {
72 static const char* getName() { return "int16_t"; }
76 class RPCTypeName<uint16_t> {
78 static const char* getName() { return "uint16_t"; }
82 class RPCTypeName<int32_t> {
84 static const char* getName() { return "int32_t"; }
88 class RPCTypeName<uint32_t> {
90 static const char* getName() { return "uint32_t"; }
94 class RPCTypeName<int64_t> {
96 static const char* getName() { return "int64_t"; }
100 class RPCTypeName<uint64_t> {
102 static const char* getName() { return "uint64_t"; }
106 class RPCTypeName<bool> {
108 static const char* getName() { return "bool"; }
112 class RPCTypeName<std::string> {
114 static const char* getName() { return "std::string"; }
117 template <typename T1, typename T2>
118 class RPCTypeName<std::pair<T1, T2>> {
120 static const char* getName() {
121 std::lock_guard<std::mutex> Lock(NameMutex);
123 raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
128 static std::mutex NameMutex;
129 static std::string Name;
132 template <typename T1, typename T2>
133 std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
134 template <typename T1, typename T2>
135 std::string RPCTypeName<std::pair<T1, T2>>::Name;
137 template <typename... ArgTs>
138 class RPCTypeName<std::tuple<ArgTs...>> {
140 static const char* getName() {
141 std::lock_guard<std::mutex> Lock(NameMutex);
143 raw_string_ostream(Name) << "std::tuple<"
144 << RPCTypeNameSequence<ArgTs...>() << ">";
148 static std::mutex NameMutex;
149 static std::string Name;
152 template <typename... ArgTs>
153 std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
154 template <typename... ArgTs>
155 std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
157 template <typename T>
158 class RPCTypeName<std::vector<T>> {
160 static const char*getName() {
161 std::lock_guard<std::mutex> Lock(NameMutex);
163 raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
169 static std::mutex NameMutex;
170 static std::string Name;
173 template <typename T>
174 std::mutex RPCTypeName<std::vector<T>>::NameMutex;
175 template <typename T>
176 std::string RPCTypeName<std::vector<T>>::Name;
179 /// The SerializationTraits<ChannelT, T> class describes how to serialize and
180 /// deserialize an instance of type T to/from an abstract channel of type
181 /// ChannelT. It also provides a representation of the type's name via the
184 /// Specializations of this class should provide the following functions:
188 /// static const char* getName();
189 /// static Error serialize(ChannelT&, const T&);
190 /// static Error deserialize(ChannelT&, T&);
194 /// The third argument of SerializationTraits is intended to support SFINAE.
199 /// class MyVirtualChannel { ... };
201 /// template <DerivedChannelT>
202 /// class SerializationTraits<DerivedChannelT, bool,
203 /// typename std::enable_if<
204 /// std::is_base_of<VirtChannel, DerivedChannel>::value
207 /// static const char* getName() { ... };
211 template <typename ChannelT, typename WireType,
212 typename ConcreteType = WireType, typename = void>
213 class SerializationTraits;
215 template <typename ChannelT>
216 class SequenceTraits {
218 static Error emitSeparator(ChannelT &C) { return Error::success(); }
219 static Error consumeSeparator(ChannelT &C) { return Error::success(); }
222 /// Utility class for serializing sequences of values of varying types.
223 /// Specializations of this class contain 'serialize' and 'deserialize' methods
224 /// for the given channel. The ArgTs... list will determine the "over-the-wire"
225 /// types to be serialized. The serialize and deserialize methods take a list
226 /// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
227 /// but may be different types from ArgTs, provided that for each CArgT there
228 /// is a SerializationTraits specialization
229 /// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
230 /// caller argument to over-the-wire value.
231 template <typename ChannelT, typename... ArgTs>
232 class SequenceSerialization;
234 template <typename ChannelT>
235 class SequenceSerialization<ChannelT> {
237 static Error serialize(ChannelT &C) { return Error::success(); }
238 static Error deserialize(ChannelT &C) { return Error::success(); }
241 template <typename ChannelT, typename ArgT>
242 class SequenceSerialization<ChannelT, ArgT> {
245 template <typename CArgT>
246 static Error serialize(ChannelT &C, const CArgT &CArg) {
247 return SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg);
250 template <typename CArgT>
251 static Error deserialize(ChannelT &C, CArgT &CArg) {
252 return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
256 template <typename ChannelT, typename ArgT, typename... ArgTs>
257 class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
260 template <typename CArgT, typename... CArgTs>
261 static Error serialize(ChannelT &C, const CArgT &CArg,
262 const CArgTs&... CArgs) {
264 SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg))
266 if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
268 return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...);
271 template <typename CArgT, typename... CArgTs>
272 static Error deserialize(ChannelT &C, CArgT &CArg,
275 SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
277 if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
279 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
283 template <typename ChannelT, typename... ArgTs>
284 Error serializeSeq(ChannelT &C, const ArgTs &... Args) {
285 return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, Args...);
288 template <typename ChannelT, typename... ArgTs>
289 Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
290 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
293 /// SerializationTraits default specialization for std::pair.
294 template <typename ChannelT, typename T1, typename T2>
295 class SerializationTraits<ChannelT, std::pair<T1, T2>> {
297 static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
298 return serializeSeq(C, V.first, V.second);
301 static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
302 return deserializeSeq(C, V.first, V.second);
306 /// SerializationTraits default specialization for std::tuple.
307 template <typename ChannelT, typename... ArgTs>
308 class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
311 /// RPC channel serialization for std::tuple.
312 static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
313 return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
316 /// RPC channel deserialization for std::tuple.
317 static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
318 return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
322 // Serialization helper for std::tuple.
323 template <size_t... Is>
324 static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
325 llvm::index_sequence<Is...> _) {
326 return serializeSeq(C, std::get<Is>(V)...);
329 // Serialization helper for std::tuple.
330 template <size_t... Is>
331 static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
332 llvm::index_sequence<Is...> _) {
333 return deserializeSeq(C, std::get<Is>(V)...);
337 /// SerializationTraits default specialization for std::vector.
338 template <typename ChannelT, typename T>
339 class SerializationTraits<ChannelT, std::vector<T>> {
342 /// Serialize a std::vector<T> from std::vector<T>.
343 static Error serialize(ChannelT &C, const std::vector<T> &V) {
344 if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
347 for (const auto &E : V)
348 if (auto Err = serializeSeq(C, E))
351 return Error::success();
354 /// Deserialize a std::vector<T> to a std::vector<T>.
355 static Error deserialize(ChannelT &C, std::vector<T> &V) {
357 if (auto Err = deserializeSeq(C, Count))
362 if (auto Err = deserializeSeq(C, E))
365 return Error::success();
369 } // end namespace rpc
370 } // end namespace orc
371 } // end namespace llvm
373 #endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H