From 29f05d96fb7bd170e73d9868883fabad98a4a38b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 2 Oct 2018 09:34:55 -0700 Subject: [PATCH] Use pthread if defined(__unix__) || defined(__APPLE__) --- src/clang_complete.cc | 33 +++++++++++++++------------------ src/messages/initialize.cc | 24 +++++++++++++++--------- src/platform.h | 2 ++ src/platform_posix.cc | 17 +++++++++++++++++ src/platform_win.cc | 6 +++++- 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/clang_complete.cc b/src/clang_complete.cc index b66a01f8..11f5b8a7 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -221,7 +221,9 @@ bool Parse(CompilerInstance &Clang) { return true; } -void CompletionPreloadMain(CompletionManager *manager) { +void *CompletionPreloadMain(void *manager_) { + auto *manager = static_cast(manager_); + set_thread_name("comp-preload"); while (true) { auto request = manager->preload_requests_.Dequeue(); @@ -246,9 +248,12 @@ void CompletionPreloadMain(CompletionManager *manager) { manager->DiagnosticsUpdate(request.path, debounce); } } + return nullptr; } -void CompletionMain(CompletionManager *manager) { +void *CompletionMain(void *manager_) { + auto *manager = static_cast(manager_); + set_thread_name("comp"); while (true) { // Fetching the completion request blocks until we have a request. std::unique_ptr request = @@ -296,6 +301,7 @@ void CompletionMain(CompletionManager *manager) { request->on_complete(&Clang->getCodeCompletionConsumer()); } + return nullptr; } llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) { @@ -326,7 +332,9 @@ void printDiag(llvm::raw_string_ostream &OS, const DiagBase &d) { OS << diagLeveltoString(d.level) << ": " << d.message; } -void DiagnosticMain(CompletionManager *manager) { +void *DiagnosticMain(void *manager_) { + auto *manager = static_cast(manager_); + set_thread_name("diag"); while (true) { CompletionManager::DiagnosticRequest request = manager->diagnostic_request_.Dequeue(); @@ -422,6 +430,7 @@ void DiagnosticMain(CompletionManager *manager) { } manager->on_diagnostic_(path, ls_diags); } + return nullptr; } } // namespace @@ -470,21 +479,9 @@ CompletionManager::CompletionManager(Project *project, preloads(kMaxPreloadedSessions), sessions(kMaxCompletionSessions), PCH(std::make_shared()) { - std::thread([&]() { - set_thread_name("comp"); - ccls::CompletionMain(this); - }) - .detach(); - std::thread([&]() { - set_thread_name("comp-preload"); - ccls::CompletionPreloadMain(this); - }) - .detach(); - std::thread([&]() { - set_thread_name("diag"); - ccls::DiagnosticMain(this); - }) - .detach(); + SpawnThread(ccls::CompletionMain, this); + SpawnThread(ccls::CompletionPreloadMain, this); + SpawnThread(ccls::DiagnosticMain, this); } void CompletionManager::DiagnosticsUpdate(const std::string &path, diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 443bf6a6..cd9d378e 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -406,6 +406,19 @@ struct Out_InitializeResponse : public lsOutMessage { MAKE_REFLECT_STRUCT(Out_InitializeResponse::InitializeResult, capabilities); MAKE_REFLECT_STRUCT(Out_InitializeResponse, jsonrpc, id, result); +void *Indexer(void *arg_) { + MessageHandler *h; + int idx; + auto *arg = static_cast *>(arg_); + std::tie(h, idx) = *arg; + delete arg; + std::string name = "indexer" + std::to_string(idx); + set_thread_name(name.c_str()); + pipeline::Indexer_Main(h->clang_complete, h->vfs, h->project, + h->working_files); + return nullptr; +} + struct Handler_Initialize : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } @@ -483,7 +496,6 @@ struct Handler_Initialize : BaseMessageHandler { idx::Init(); - // Open up / load the project. project->Load(project_path); // Start indexer threads. Start this after loading the project, as that @@ -493,14 +505,8 @@ struct Handler_Initialize : BaseMessageHandler { g_config->index.threads = std::thread::hardware_concurrency(); LOG_S(INFO) << "start " << g_config->index.threads << " indexers"; - for (int i = 0; i < g_config->index.threads; i++) { - std::thread([=]() { - std::string name = "indexer" + std::to_string(i); - set_thread_name(name.c_str()); - pipeline::Indexer_Main(clang_complete, vfs, project, working_files); - }) - .detach(); - } + for (int i = 0; i < g_config->index.threads; i++) + SpawnThread(Indexer, new std::pair{this, i}); // Start scanning include directories before dispatching project // files, because that takes a long time. diff --git a/src/platform.h b/src/platform.h index 46e88307..076860f5 100644 --- a/src/platform.h +++ b/src/platform.h @@ -29,3 +29,5 @@ void TraceMe(); std::string GetExternalCommandOutput(const std::vector &command, std::string_view input); + +void SpawnThread(void *(*fn)(void *), void *arg); diff --git a/src/platform_posix.cc b/src/platform_posix.cc index 1d2d59a9..ed2f92df 100644 --- a/src/platform_posix.cc +++ b/src/platform_posix.cc @@ -28,7 +28,9 @@ limitations under the License. #include #include #include +#include #include +#include #include #include // required for stat.h #include @@ -169,4 +171,19 @@ std::string GetExternalCommandOutput(const std::vector &command, return ret; } +void SpawnThread(void *(*fn)(void *), void *arg) { + pthread_t thd; + pthread_attr_t attr; + struct rlimit rlim; + size_t stack_size = 4 * 1024 * 1024; + if (getrlimit(RLIMIT_STACK, &rlim) == 0 && + rlim.rlim_cur != RLIM_INFINITY) + stack_size = rlim.rlim_cur; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setstacksize(&attr, stack_size); + pthread_create(&thd, &attr, fn, arg); + pthread_attr_destroy(&attr); +} + #endif diff --git a/src/platform_win.cc b/src/platform_win.cc index 3acbe7e2..797644c8 100644 --- a/src/platform_win.cc +++ b/src/platform_win.cc @@ -27,8 +27,8 @@ limitations under the License. #include #include -#include #include +#include std::string NormalizePath(const std::string &path) { DWORD retval = 0; @@ -61,4 +61,8 @@ std::string GetExternalCommandOutput(const std::vector &command, return ""; } +void SpawnThread(void *(*fn)(void *), void *arg) { + std::thread(fn, arg).detach(); +} + #endif