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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits