From 31314555bb8bca6431f0c257b7272fd7c65395b5 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 799830f0..be8daf57 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -209,7 +209,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(); @@ -234,9 +236,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 = @@ -284,6 +289,7 @@ void CompletionMain(CompletionManager *manager) { request->on_complete(&Clang->getCodeCompletionConsumer()); } + return nullptr; } llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) { @@ -314,7 +320,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(); @@ -410,6 +418,7 @@ void DiagnosticMain(CompletionManager *manager) { } manager->on_diagnostic_(path, ls_diags); } + return nullptr; } } // namespace @@ -459,21 +468,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 f219d1e6..f9a79770 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -394,6 +394,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; } @@ -471,7 +484,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 @@ -481,14 +493,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 2b3fb8f6..6f1e7658 100644 --- a/src/platform.h +++ b/src/platform.h @@ -17,3 +17,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 7119aa3d..e617f43b 100644 --- a/src/platform_posix.cc +++ b/src/platform_posix.cc @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include // required for stat.h #include @@ -157,4 +159,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 36ebc839..a051cd7b 100644 --- a/src/platform_win.cc +++ b/src/platform_win.cc @@ -15,8 +15,8 @@ #include #include -#include #include +#include std::string NormalizePath(const std::string &path) { DWORD retval = 0; @@ -49,4 +49,8 @@ std::string GetExternalCommandOutput(const std::vector &command, return ""; } +void SpawnThread(void *(*fn)(void *), void *arg) { + std::thread(fn, arg).detach(); +} + #endif