diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-02-22 17:03:21 +0100 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-02-22 17:03:21 +0100 |
commit | 619def44c1cca9f3cdf63544d5f24f2c7a7d9b77 (patch) | |
tree | 01868de723cb82c86842f33743fa7b14e24c1fa3 /src/buildtool/multithreading/task_system.cpp | |
download | justbuild-619def44c1cca9f3cdf63544d5f24f2c7a7d9b77.tar.gz |
Initial self-hosting commit
This is the initial version of our tool that is able to
build itself. In can be bootstrapped by
./bin/bootstrap.py
Co-authored-by: Oliver Reiche <oliver.reiche@huawei.com>
Co-authored-by: Victor Moreno <victor.moreno1@huawei.com>
Diffstat (limited to 'src/buildtool/multithreading/task_system.cpp')
-rw-r--r-- | src/buildtool/multithreading/task_system.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/buildtool/multithreading/task_system.cpp b/src/buildtool/multithreading/task_system.cpp new file mode 100644 index 00000000..8c976a2f --- /dev/null +++ b/src/buildtool/multithreading/task_system.cpp @@ -0,0 +1,56 @@ +#include "src/buildtool/multithreading/task_system.hpp" + +#include "gsl-lite/gsl-lite.hpp" +#include "src/buildtool/multithreading/task.hpp" + +TaskSystem::TaskSystem() : TaskSystem(std::thread::hardware_concurrency()) {} + +TaskSystem::TaskSystem(std::size_t number_of_threads) + : thread_count_{std::max(1UL, number_of_threads)}, + num_threads_running_{thread_count_} { + for (std::size_t index = 0; index < thread_count_; ++index) { + queues_.emplace_back(&queues_read_, &num_threads_running_); + } + for (std::size_t index = 0; index < thread_count_; ++index) { + threads_.emplace_back([&, index]() { Run(index); }); + } +} + +TaskSystem::~TaskSystem() { + // When starting a new task system all spawned threads will immediately go + // to sleep and wait for tasks. Even after adding some tasks, it can take a + // while until the first thread wakes up. Therefore, we first need to wait + // for the queues being read, before we can wait for all threads to become + // idle. + queues_read_.WaitForSet(); + num_threads_running_.WaitForZero(); + for (auto& q : queues_) { + q.done(); + } + for (auto& t : threads_) { + t.join(); + } +} + +void TaskSystem::Run(std::size_t idx) { + gsl_Expects(thread_count_ > 0); + + while (true) { + std::optional<Task> t{}; + for (std::size_t i = 0; i < thread_count_; ++i) { + t = queues_[(idx + i) % thread_count_].try_pop(); + if (t) { + break; + } + } + + // NOLINTNEXTLINE(clang-analyzer-core.DivideZero) + t = t ? t : queues_[idx % thread_count_].pop(); + + if (!t) { + break; + } + + (*t)(); + } +} |