[clang-tools-extra] r294747 - [clangd] Refactor stream output into a single thread-safe output object.

Benjamin Kramer via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 10 06:08:41 PST 2017


Author: d0k
Date: Fri Feb 10 08:08:40 2017
New Revision: 294747

URL: http://llvm.org/viewvc/llvm-project?rev=294747&view=rev
Log:
[clangd] Refactor stream output into a single thread-safe output object.

This abstracts away the passing of raw_ostreams everywhere, thread
safety will be used soon.

Modified:
    clang-tools-extra/trunk/clangd/ClangDMain.cpp
    clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
    clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
    clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
    clang-tools-extra/trunk/clangd/ProtocolHandlers.h

Modified: clang-tools-extra/trunk/clangd/ClangDMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangDMain.cpp?rev=294747&r1=294746&r2=294747&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangDMain.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangDMain.cpp Fri Feb 10 08:08:40 2017
@@ -19,6 +19,7 @@ using namespace clang::clangd;
 int main(int argc, char *argv[]) {
   llvm::raw_ostream &Outs = llvm::outs();
   llvm::raw_ostream &Logs = llvm::errs();
+  JSONOutput Out(Outs, Logs);
 
   // Change stdin to binary to not lose \r\n on windows.
   llvm::sys::ChangeStdinToBinary();
@@ -26,24 +27,24 @@ int main(int argc, char *argv[]) {
   // Set up a document store and intialize all the method handlers for JSONRPC
   // dispatching.
   DocumentStore Store;
-  JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Outs, Logs));
+  JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Out));
   Dispatcher.registerHandler("initialize",
-                             llvm::make_unique<InitializeHandler>(Outs, Logs));
+                             llvm::make_unique<InitializeHandler>(Out));
   Dispatcher.registerHandler("shutdown",
-                             llvm::make_unique<ShutdownHandler>(Outs, Logs));
+                             llvm::make_unique<ShutdownHandler>(Out));
   Dispatcher.registerHandler(
       "textDocument/didOpen",
-      llvm::make_unique<TextDocumentDidOpenHandler>(Outs, Logs, Store));
+      llvm::make_unique<TextDocumentDidOpenHandler>(Out, Store));
   // FIXME: Implement textDocument/didClose.
   Dispatcher.registerHandler(
       "textDocument/didChange",
-      llvm::make_unique<TextDocumentDidChangeHandler>(Outs, Logs, Store));
+      llvm::make_unique<TextDocumentDidChangeHandler>(Out, Store));
   Dispatcher.registerHandler(
       "textDocument/rangeFormatting",
-      llvm::make_unique<TextDocumentRangeFormattingHandler>(Outs, Logs, Store));
+      llvm::make_unique<TextDocumentRangeFormattingHandler>(Out, Store));
   Dispatcher.registerHandler(
       "textDocument/formatting",
-      llvm::make_unique<TextDocumentFormattingHandler>(Outs, Logs, Store));
+      llvm::make_unique<TextDocumentFormattingHandler>(Out, Store));
 
   while (std::cin.good()) {
     // A Language Server Protocol message starts with a HTTP header, delimited
@@ -89,6 +90,10 @@ int main(int argc, char *argv[]) {
       // Finally, execute the action for this JSON message.
       if (!Dispatcher.call(JSONRef))
         Logs << "JSON dispatch failed!\n";
+
+      // If we're done, exit the loop.
+      if (Out.isDone())
+        break;
     }
   }
 }

Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp?rev=294747&r1=294746&r2=294747&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp (original)
+++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp Fri Feb 10 08:08:40 2017
@@ -15,10 +15,11 @@
 using namespace clang;
 using namespace clangd;
 
-void Handler::writeMessage(const Twine &Message) {
+void JSONOutput::writeMessage(const Twine &Message) {
   llvm::SmallString<128> Storage;
   StringRef M = Message.toStringRef(Storage);
 
+  std::lock_guard<std::mutex> Guard(StreamMutex);
   // Log without headers.
   Logs << "--> " << M << '\n';
   Logs.flush();
@@ -29,7 +30,7 @@ void Handler::writeMessage(const Twine &
 }
 
 void Handler::handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) {
-  Logs << "Method ignored.\n";
+  Output.logs() << "Method ignored.\n";
   // Return that this method is unsupported.
   writeMessage(
       R"({"jsonrpc":"2.0","id":)" + ID +
@@ -37,7 +38,7 @@ void Handler::handleMethod(llvm::yaml::M
 }
 
 void Handler::handleNotification(llvm::yaml::MappingNode *Params) {
-  Logs << "Notification ignored.\n";
+  Output.logs() << "Notification ignored.\n";
 }
 
 void JSONRPCDispatcher::registerHandler(StringRef Method,

Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h?rev=294747&r1=294746&r2=294747&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h (original)
+++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h Fri Feb 10 08:08:40 2017
@@ -13,15 +13,42 @@
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/YAMLParser.h"
+#include <mutex>
 
 namespace clang {
 namespace clangd {
 
+/// Encapsulates output and logs streams and provides thread-safe access to
+/// them.
+class JSONOutput {
+public:
+  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
+      : Outs(Outs), Logs(Logs) {}
+
+  /// Emit a JSONRPC message.
+  void writeMessage(const Twine &Message);
+
+  /// Get the logging stream.
+  llvm::raw_ostream &logs() { return Logs; }
+
+  /// Use this to indicate that the output stream should be closed and the
+  /// process should terminate.
+  void setDone() { Done = true; }
+  bool isDone() const { return Done; }
+
+private:
+  llvm::raw_ostream &Outs;
+  llvm::raw_ostream &Logs;
+
+  bool Done = false;
+
+  std::mutex StreamMutex;
+};
+
 /// Callback for messages sent to the server, called by the JSONRPCDispatcher.
 class Handler {
 public:
-  Handler(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
-      : Outs(Outs), Logs(Logs) {}
+  Handler(JSONOutput &Output) : Output(Output) {}
   virtual ~Handler() = default;
 
   /// Called when the server receives a method call. This is supposed to return
@@ -33,11 +60,10 @@ public:
   virtual void handleNotification(llvm::yaml::MappingNode *Params);
 
 protected:
-  llvm::raw_ostream &Outs;
-  llvm::raw_ostream &Logs;
+  JSONOutput &Output;
 
-  /// Helper to write a JSONRPC result to Outs.
-  void writeMessage(const Twine &Message);
+  /// Helper to write a JSONRPC result to Output.
+  void writeMessage(const Twine &Message) { Output.writeMessage(Message); }
 };
 
 /// Main JSONRPC entry point. This parses the JSONRPC "header" and calls the

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=294747&r1=294746&r2=294747&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Fri Feb 10 08:08:40 2017
@@ -17,7 +17,7 @@ void TextDocumentDidOpenHandler::handleN
     llvm::yaml::MappingNode *Params) {
   auto DOTDP = DidOpenTextDocumentParams::parse(Params);
   if (!DOTDP) {
-    Logs << "Failed to decode DidOpenTextDocumentParams!\n";
+    Output.logs() << "Failed to decode DidOpenTextDocumentParams!\n";
     return;
   }
   Store.addDocument(DOTDP->textDocument.uri, DOTDP->textDocument.text);
@@ -27,7 +27,7 @@ void TextDocumentDidChangeHandler::handl
     llvm::yaml::MappingNode *Params) {
   auto DCTDP = DidChangeTextDocumentParams::parse(Params);
   if (!DCTDP || DCTDP->contentChanges.size() != 1) {
-    Logs << "Failed to decode DidChangeTextDocumentParams!\n";
+    Output.logs() << "Failed to decode DidChangeTextDocumentParams!\n";
     return;
   }
   // We only support full syncing right now.
@@ -91,7 +91,7 @@ void TextDocumentRangeFormattingHandler:
     llvm::yaml::MappingNode *Params, StringRef ID) {
   auto DRFP = DocumentRangeFormattingParams::parse(Params);
   if (!DRFP) {
-    Logs << "Failed to decode DocumentRangeFormattingParams!\n";
+    Output.logs() << "Failed to decode DocumentRangeFormattingParams!\n";
     return;
   }
 
@@ -108,7 +108,7 @@ void TextDocumentFormattingHandler::hand
     llvm::yaml::MappingNode *Params, StringRef ID) {
   auto DFP = DocumentFormattingParams::parse(Params);
   if (!DFP) {
-    Logs << "Failed to decode DocumentFormattingParams!\n";
+    Output.logs() << "Failed to decode DocumentFormattingParams!\n";
     return;
   }
 

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.h?rev=294747&r1=294746&r2=294747&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.h (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.h Fri Feb 10 08:08:40 2017
@@ -25,8 +25,7 @@ namespace clangd {
 class DocumentStore;
 
 struct InitializeHandler : Handler {
-  InitializeHandler(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
-      : Handler(Outs, Logs) {}
+  InitializeHandler(JSONOutput &Output) : Handler(Output) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
     writeMessage(
@@ -40,19 +39,16 @@ struct InitializeHandler : Handler {
 };
 
 struct ShutdownHandler : Handler {
-  ShutdownHandler(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
-      : Handler(Outs, Logs) {}
+  ShutdownHandler(JSONOutput &Output) : Handler(Output) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    // FIXME: Calling exit is rude, can we communicate to main somehow?
-    exit(0);
+    Output.setDone();
   }
 };
 
 struct TextDocumentDidOpenHandler : Handler {
-  TextDocumentDidOpenHandler(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
-                             DocumentStore &Store)
-      : Handler(Outs, Logs), Store(Store) {}
+  TextDocumentDidOpenHandler(JSONOutput &Output, DocumentStore &Store)
+      : Handler(Output), Store(Store) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override;
 
@@ -61,9 +57,8 @@ private:
 };
 
 struct TextDocumentDidChangeHandler : Handler {
-  TextDocumentDidChangeHandler(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
-                               DocumentStore &Store)
-      : Handler(Outs, Logs), Store(Store) {}
+  TextDocumentDidChangeHandler(JSONOutput &Output, DocumentStore &Store)
+      : Handler(Output), Store(Store) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override;
 
@@ -72,10 +67,8 @@ private:
 };
 
 struct TextDocumentRangeFormattingHandler : Handler {
-  TextDocumentRangeFormattingHandler(llvm::raw_ostream &Outs,
-                                     llvm::raw_ostream &Logs,
-                                     DocumentStore &Store)
-      : Handler(Outs, Logs), Store(Store) {}
+  TextDocumentRangeFormattingHandler(JSONOutput &Output, DocumentStore &Store)
+      : Handler(Output), Store(Store) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 
@@ -84,9 +77,8 @@ private:
 };
 
 struct TextDocumentFormattingHandler : Handler {
-  TextDocumentFormattingHandler(llvm::raw_ostream &Outs,
-                                llvm::raw_ostream &Logs, DocumentStore &Store)
-      : Handler(Outs, Logs), Store(Store) {}
+  TextDocumentFormattingHandler(JSONOutput &Output, DocumentStore &Store)
+      : Handler(Output), Store(Store) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override;
 




More information about the cfe-commits mailing list