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"
26 /// TypeNameSequence is a utility for rendering sequences of types to a string
27 /// by rendering each type, separated by ", ".
28 template <typename... ArgTs> class RPCTypeNameSequence {};
30 /// Render an empty TypeNameSequence to an ostream.
31 template <typename OStream>
32 OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
36 /// Render a TypeNameSequence of a single type to an ostream.
37 template <typename OStream, typename ArgT>
38 OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
39 OS << RPCTypeName<ArgT>::getName();
43 /// Render a TypeNameSequence of more than one type to an ostream.
44 template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
46 operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
47 OS << RPCTypeName<ArgT1>::getName() << ", "
48 << RPCTypeNameSequence<ArgT2, ArgTs...>();
53 class RPCTypeName<void> {
55 static const char* getName() { return "void"; }
59 class RPCTypeName<int8_t> {
61 static const char* getName() { return "int8_t"; }
65 class RPCTypeName<uint8_t> {
67 static const char* getName() { return "uint8_t"; }
71 class RPCTypeName<int16_t> {
73 static const char* getName() { return "int16_t"; }
77 class RPCTypeName<uint16_t> {
79 static const char* getName() { return "uint16_t"; }
83 class RPCTypeName<int32_t> {
85 static const char* getName() { return "int32_t"; }
89 class RPCTypeName<uint32_t> {
91 static const char* getName() { return "uint32_t"; }
95 class RPCTypeName<int64_t> {
97 static const char* getName() { return "int64_t"; }
101 class RPCTypeName<uint64_t> {
103 static const char* getName() { return "uint64_t"; }
107 class RPCTypeName<bool> {
109 static const char* getName() { return "bool"; }
113 class RPCTypeName<std::string> {
115 static const char* getName() { return "std::string"; }
119 class RPCTypeName<Error> {
121 static const char* getName() { return "Error"; }
124 template <typename T>
125 class RPCTypeName<Expected<T>> {
127 static const char* getName() {
128 std::lock_guard<std::mutex> Lock(NameMutex);
130 raw_string_ostream(Name) << "Expected<"
131 << RPCTypeNameSequence<T>()
137 static std::mutex NameMutex;
138 static std::string Name;
141 template <typename T>
142 std::mutex RPCTypeName<Expected<T>>::NameMutex;
144 template <typename T>
145 std::string RPCTypeName<Expected<T>>::Name;
147 template <typename T1, typename T2>
148 class RPCTypeName<std::pair<T1, T2>> {
150 static const char* getName() {
151 std::lock_guard<std::mutex> Lock(NameMutex);
153 raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
158 static std::mutex NameMutex;
159 static std::string Name;
162 template <typename T1, typename T2>
163 std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
164 template <typename T1, typename T2>
165 std::string RPCTypeName<std::pair<T1, T2>>::Name;
167 template <typename... ArgTs>
168 class RPCTypeName<std::tuple<ArgTs...>> {
170 static const char* getName() {
171 std::lock_guard<std::mutex> Lock(NameMutex);
173 raw_string_ostream(Name) << "std::tuple<"
174 << RPCTypeNameSequence<ArgTs...>() << ">";
178 static std::mutex NameMutex;
179 static std::string Name;
182 template <typename... ArgTs>
183 std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
184 template <typename... ArgTs>
185 std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
187 template <typename T>
188 class RPCTypeName<std::vector<T>> {
190 static const char*getName() {
191 std::lock_guard<std::mutex> Lock(NameMutex);
193 raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
199 static std::mutex NameMutex;
200 static std::string Name;
203 template <typename T>
204 std::mutex RPCTypeName<std::vector<T>>::NameMutex;
205 template <typename T>
206 std::string RPCTypeName<std::vector<T>>::Name;
209 /// The SerializationTraits<ChannelT, T> class describes how to serialize and
210 /// deserialize an instance of type T to/from an abstract channel of type
211 /// ChannelT. It also provides a representation of the type's name via the
214 /// Specializations of this class should provide the following functions:
218 /// static const char* getName();
219 /// static Error serialize(ChannelT&, const T&);
220 /// static Error deserialize(ChannelT&, T&);
224 /// The third argument of SerializationTraits is intended to support SFINAE.
229 /// class MyVirtualChannel { ... };
231 /// template <DerivedChannelT>
232 /// class SerializationTraits<DerivedChannelT, bool,
233 /// typename std::enable_if<
234 /// std::is_base_of<VirtChannel, DerivedChannel>::value
237 /// static const char* getName() { ... };
241 template <typename ChannelT, typename WireType,
242 typename ConcreteType = WireType, typename = void>
243 class SerializationTraits;
245 template <typename ChannelT>
246 class SequenceTraits {
248 static Error emitSeparator(ChannelT &C) { return Error::success(); }
249 static Error consumeSeparator(ChannelT &C) { return Error::success(); }
252 /// Utility class for serializing sequences of values of varying types.
253 /// Specializations of this class contain 'serialize' and 'deserialize' methods
254 /// for the given channel. The ArgTs... list will determine the "over-the-wire"
255 /// types to be serialized. The serialize and deserialize methods take a list
256 /// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
257 /// but may be different types from ArgTs, provided that for each CArgT there
258 /// is a SerializationTraits specialization
259 /// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
260 /// caller argument to over-the-wire value.
261 template <typename ChannelT, typename... ArgTs>
262 class SequenceSerialization;
264 template <typename ChannelT>
265 class SequenceSerialization<ChannelT> {
267 static Error serialize(ChannelT &C) { return Error::success(); }
268 static Error deserialize(ChannelT &C) { return Error::success(); }
271 template <typename ChannelT, typename ArgT>
272 class SequenceSerialization<ChannelT, ArgT> {
275 template <typename CArgT>
276 static Error serialize(ChannelT &C, CArgT &&CArg) {
277 return SerializationTraits<ChannelT, ArgT,
278 typename std::decay<CArgT>::type>::
279 serialize(C, std::forward<CArgT>(CArg));
282 template <typename CArgT>
283 static Error deserialize(ChannelT &C, CArgT &CArg) {
284 return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
288 template <typename ChannelT, typename ArgT, typename... ArgTs>
289 class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
292 template <typename CArgT, typename... CArgTs>
293 static Error serialize(ChannelT &C, CArgT &&CArg,
294 CArgTs &&... CArgs) {
296 SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>::
297 serialize(C, std::forward<CArgT>(CArg)))
299 if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
301 return SequenceSerialization<ChannelT, ArgTs...>::
302 serialize(C, std::forward<CArgTs>(CArgs)...);
305 template <typename CArgT, typename... CArgTs>
306 static Error deserialize(ChannelT &C, CArgT &CArg,
309 SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
311 if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
313 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
317 template <typename ChannelT, typename... ArgTs>
318 Error serializeSeq(ChannelT &C, ArgTs &&... Args) {
319 return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>::
320 serialize(C, std::forward<ArgTs>(Args)...);
323 template <typename ChannelT, typename... ArgTs>
324 Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
325 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
328 template <typename ChannelT>
329 class SerializationTraits<ChannelT, Error> {
332 using WrappedErrorSerializer =
333 std::function<Error(ChannelT &C, const ErrorInfoBase&)>;
335 using WrappedErrorDeserializer =
336 std::function<Error(ChannelT &C, Error &Err)>;
338 template <typename ErrorInfoT, typename SerializeFtor,
339 typename DeserializeFtor>
340 static void registerErrorType(std::string Name, SerializeFtor Serialize,
341 DeserializeFtor Deserialize) {
342 assert(!Name.empty() &&
343 "The empty string is reserved for the Success value");
345 const std::string *KeyName = nullptr;
347 // We're abusing the stability of std::map here: We take a reference to the
348 // key of the deserializers map to save us from duplicating the string in
349 // the serializer. This should be changed to use a stringpool if we switch
350 // to a map type that may move keys in memory.
351 std::lock_guard<std::mutex> Lock(DeserializersMutex);
353 Deserializers.insert(Deserializers.begin(),
354 std::make_pair(std::move(Name),
355 std::move(Deserialize)));
360 assert(KeyName != nullptr && "No keyname pointer");
361 std::lock_guard<std::mutex> Lock(SerializersMutex);
362 // FIXME: Move capture Serialize once we have C++14.
363 Serializers[ErrorInfoT::classID()] =
364 [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
365 assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&
366 "Serializer called for wrong error type");
367 if (auto Err = serializeSeq(C, *KeyName))
369 return Serialize(C, static_cast<const ErrorInfoT&>(EIB));
374 static Error serialize(ChannelT &C, Error &&Err) {
375 std::lock_guard<std::mutex> Lock(SerializersMutex);
377 return serializeSeq(C, std::string());
379 return handleErrors(std::move(Err),
380 [&C](const ErrorInfoBase &EIB) {
381 auto SI = Serializers.find(EIB.dynamicClassID());
382 if (SI == Serializers.end())
383 return serializeAsStringError(C, EIB);
384 return (SI->second)(C, EIB);
388 static Error deserialize(ChannelT &C, Error &Err) {
389 std::lock_guard<std::mutex> Lock(DeserializersMutex);
392 if (auto Err = deserializeSeq(C, Key))
396 ErrorAsOutParameter EAO(&Err);
397 Err = Error::success();
398 return Error::success();
401 auto DI = Deserializers.find(Key);
402 assert(DI != Deserializers.end() && "No deserializer for error type");
403 return (DI->second)(C, Err);
408 static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) {
409 assert(EIB.dynamicClassID() != StringError::classID() &&
410 "StringError serialization not registered");
413 raw_string_ostream ErrMsgStream(ErrMsg);
414 EIB.log(ErrMsgStream);
416 return serialize(C, make_error<StringError>(std::move(ErrMsg),
417 inconvertibleErrorCode()));
420 static std::mutex SerializersMutex;
421 static std::mutex DeserializersMutex;
422 static std::map<const void*, WrappedErrorSerializer> Serializers;
423 static std::map<std::string, WrappedErrorDeserializer> Deserializers;
426 template <typename ChannelT>
427 std::mutex SerializationTraits<ChannelT, Error>::SerializersMutex;
429 template <typename ChannelT>
430 std::mutex SerializationTraits<ChannelT, Error>::DeserializersMutex;
432 template <typename ChannelT>
433 std::map<const void*,
434 typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer>
435 SerializationTraits<ChannelT, Error>::Serializers;
437 template <typename ChannelT>
438 std::map<std::string,
439 typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer>
440 SerializationTraits<ChannelT, Error>::Deserializers;
442 template <typename ChannelT>
443 void registerStringError() {
444 static bool AlreadyRegistered = false;
445 if (!AlreadyRegistered) {
446 SerializationTraits<ChannelT, Error>::
447 template registerErrorType<StringError>(
449 [](ChannelT &C, const StringError &SE) {
450 return serializeSeq(C, SE.getMessage());
452 [](ChannelT &C, Error &Err) {
453 ErrorAsOutParameter EAO(&Err);
455 if (auto E2 = deserializeSeq(C, Msg))
458 make_error<StringError>(std::move(Msg),
460 OrcErrorCode::UnknownErrorCodeFromRemote));
461 return Error::success();
463 AlreadyRegistered = true;
467 /// SerializationTraits for Expected<T1> from an Expected<T2>.
468 template <typename ChannelT, typename T1, typename T2>
469 class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> {
472 static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) {
474 if (auto Err = serializeSeq(C, true))
476 return SerializationTraits<ChannelT, T1, T2>::serialize(C, *ValOrErr);
478 if (auto Err = serializeSeq(C, false))
480 return serializeSeq(C, ValOrErr.takeError());
483 static Error deserialize(ChannelT &C, Expected<T2> &ValOrErr) {
484 ExpectedAsOutParameter<T2> EAO(&ValOrErr);
486 if (auto Err = deserializeSeq(C, HasValue))
489 return SerializationTraits<ChannelT, T1, T2>::deserialize(C, *ValOrErr);
490 Error Err = Error::success();
491 if (auto E2 = deserializeSeq(C, Err))
493 ValOrErr = std::move(Err);
494 return Error::success();
498 /// SerializationTraits for Expected<T1> from a T2.
499 template <typename ChannelT, typename T1, typename T2>
500 class SerializationTraits<ChannelT, Expected<T1>, T2> {
503 static Error serialize(ChannelT &C, T2 &&Val) {
504 return serializeSeq(C, Expected<T2>(std::forward<T2>(Val)));
508 /// SerializationTraits for Expected<T1> from an Error.
509 template <typename ChannelT, typename T>
510 class SerializationTraits<ChannelT, Expected<T>, Error> {
513 static Error serialize(ChannelT &C, Error &&Err) {
514 return serializeSeq(C, Expected<T>(std::move(Err)));
518 /// SerializationTraits default specialization for std::pair.
519 template <typename ChannelT, typename T1, typename T2>
520 class SerializationTraits<ChannelT, std::pair<T1, T2>> {
522 static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
523 return serializeSeq(C, V.first, V.second);
526 static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
527 return deserializeSeq(C, V.first, V.second);
531 /// SerializationTraits default specialization for std::tuple.
532 template <typename ChannelT, typename... ArgTs>
533 class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
536 /// RPC channel serialization for std::tuple.
537 static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
538 return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
541 /// RPC channel deserialization for std::tuple.
542 static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
543 return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
547 // Serialization helper for std::tuple.
548 template <size_t... Is>
549 static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
550 llvm::index_sequence<Is...> _) {
551 return serializeSeq(C, std::get<Is>(V)...);
554 // Serialization helper for std::tuple.
555 template <size_t... Is>
556 static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
557 llvm::index_sequence<Is...> _) {
558 return deserializeSeq(C, std::get<Is>(V)...);
562 /// SerializationTraits default specialization for std::vector.
563 template <typename ChannelT, typename T>
564 class SerializationTraits<ChannelT, std::vector<T>> {
567 /// Serialize a std::vector<T> from std::vector<T>.
568 static Error serialize(ChannelT &C, const std::vector<T> &V) {
569 if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
572 for (const auto &E : V)
573 if (auto Err = serializeSeq(C, E))
576 return Error::success();
579 /// Deserialize a std::vector<T> to a std::vector<T>.
580 static Error deserialize(ChannelT &C, std::vector<T> &V) {
582 if (auto Err = deserializeSeq(C, Count))
587 if (auto Err = deserializeSeq(C, E))
590 return Error::success();
594 } // end namespace rpc
595 } // end namespace orc
596 } // end namespace llvm
598 #endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H