From 70eccdc7275eecd3ca8241910b9f7dc95ebdef9d Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sun, 23 Apr 2017 23:36:13 +0000 Subject: [PATCH] [Orc] Use recursive mutexes for Error serialization. Errors can be nested, so we need recursive locking for serialization / deserialization. llvm-svn: 301147 --- .../llvm/ExecutionEngine/Orc/RPCSerialization.h | 67 +++++++++++++--------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h index 84a037b..a300845 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h @@ -348,7 +348,7 @@ public: // key of the deserializers map to save us from duplicating the string in // the serializer. This should be changed to use a stringpool if we switch // to a map type that may move keys in memory. - std::lock_guard Lock(DeserializersMutex); + std::lock_guard Lock(DeserializersMutex); auto I = Deserializers.insert(Deserializers.begin(), std::make_pair(std::move(Name), @@ -358,7 +358,7 @@ public: { assert(KeyName != nullptr && "No keyname pointer"); - std::lock_guard Lock(SerializersMutex); + std::lock_guard Lock(SerializersMutex); // FIXME: Move capture Serialize once we have C++14. Serializers[ErrorInfoT::classID()] = [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error { @@ -372,12 +372,13 @@ public: } static Error serialize(ChannelT &C, Error &&Err) { - std::lock_guard Lock(SerializersMutex); + std::lock_guard Lock(SerializersMutex); + if (!Err) return serializeSeq(C, std::string()); return handleErrors(std::move(Err), - [&C](const ErrorInfoBase &EIB) { + [&C, &Lock](const ErrorInfoBase &EIB) { auto SI = Serializers.find(EIB.dynamicClassID()); if (SI == Serializers.end()) return serializeAsStringError(C, EIB); @@ -386,7 +387,7 @@ public: } static Error deserialize(ChannelT &C, Error &Err) { - std::lock_guard Lock(DeserializersMutex); + std::lock_guard Lock(DeserializersMutex); std::string Key; if (auto Err = deserializeSeq(C, Key)) @@ -406,8 +407,6 @@ public: private: static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) { - assert(EIB.dynamicClassID() != StringError::classID() && - "StringError serialization not registered"); std::string ErrMsg; { raw_string_ostream ErrMsgStream(ErrMsg); @@ -417,17 +416,17 @@ private: inconvertibleErrorCode())); } - static std::mutex SerializersMutex; - static std::mutex DeserializersMutex; + static std::recursive_mutex SerializersMutex; + static std::recursive_mutex DeserializersMutex; static std::map Serializers; static std::map Deserializers; }; template -std::mutex SerializationTraits::SerializersMutex; +std::recursive_mutex SerializationTraits::SerializersMutex; template -std::mutex SerializationTraits::DeserializersMutex; +std::recursive_mutex SerializationTraits::DeserializersMutex; template std::map::WrappedErrorDeserializer> SerializationTraits::Deserializers; +/// Registers a serializer and deserializer for the given error type on the +/// given channel type. +template +void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize, + DeserializeFtor &&Deserialize) { + SerializationTraits::template registerErrorType( + std::move(Name), + std::forward(Serialize), + std::forward(Deserialize)); +} + +/// Registers serialization/deserialization for StringError. template void registerStringError() { static bool AlreadyRegistered = false; if (!AlreadyRegistered) { - SerializationTraits:: - template registerErrorType( - "StringError", - [](ChannelT &C, const StringError &SE) { - return serializeSeq(C, SE.getMessage()); - }, - [](ChannelT &C, Error &Err) { - ErrorAsOutParameter EAO(&Err); - std::string Msg; - if (auto E2 = deserializeSeq(C, Msg)) - return E2; - Err = - make_error(std::move(Msg), - orcError( - OrcErrorCode::UnknownErrorCodeFromRemote)); - return Error::success(); - }); + registerErrorSerialization( + "StringError", + [](ChannelT &C, const StringError &SE) { + return serializeSeq(C, SE.getMessage()); + }, + [](ChannelT &C, Error &Err) -> Error { + ErrorAsOutParameter EAO(&Err); + std::string Msg; + if (auto E2 = deserializeSeq(C, Msg)) + return E2; + Err = + make_error(std::move(Msg), + orcError( + OrcErrorCode::UnknownErrorCodeFromRemote)); + return Error::success(); + }); AlreadyRegistered = true; } } -- 2.7.4