template <typename T>
OutgoingNotification<T> outgoingNotification(llvm::StringLiteral method) {
return [&, method](const T ¶ms) {
+ std::lock_guard<std::mutex> transportLock(transportOutputMutex);
Logger::info("--> {0}", method);
transport.notify(method, llvm::json::Value(params));
};
methodHandlers;
JSONTransport &transport;
+
+ /// Mutex to guard sending output messages to the transport.
+ std::mutex transportOutputMutex;
};
} // namespace lsp
/// - if there were multiple replies, only the first is sent
class Reply {
public:
- Reply(const llvm::json::Value &id, StringRef method,
- JSONTransport &transport);
+ Reply(const llvm::json::Value &id, StringRef method, JSONTransport &transport,
+ std::mutex &transportOutputMutex);
Reply(Reply &&other);
Reply &operator=(Reply &&) = delete;
Reply(const Reply &) = delete;
std::atomic<bool> replied = {false};
llvm::json::Value id;
JSONTransport *transport;
+ std::mutex &transportOutputMutex;
};
} // namespace
Reply::Reply(const llvm::json::Value &id, llvm::StringRef method,
- JSONTransport &transport)
- : id(id), transport(&transport) {}
+ JSONTransport &transport, std::mutex &transportOutputMutex)
+ : id(id), transport(&transport),
+ transportOutputMutex(transportOutputMutex) {}
Reply::Reply(Reply &&other)
: replied(other.replied.load()), id(std::move(other.id)),
- transport(other.transport) {
+ transport(other.transport),
+ transportOutputMutex(other.transportOutputMutex) {
other.transport = nullptr;
}
}
assert(transport && "expected valid transport to reply to");
+ std::lock_guard<std::mutex> transportLock(transportOutputMutex);
if (reply) {
Logger::info("--> reply:{0}({1})", method, id);
transport->reply(std::move(id), std::move(reply));
llvm::json::Value id) {
Logger::info("--> {0}({1})", method, id);
- Reply reply(id, method, transport);
+ Reply reply(id, method, transport, transportOutputMutex);
auto it = methodHandlers.find(method);
if (it != methodHandlers.end()) {