| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #include <cassert>
- #include <cstddef>
- #include <deque>
- #include <iostream>
- #include <vector>
- #include <cm/optional>
- #include <cm3p/uv.h>
- #ifndef _WIN32
- # include <unistd.h>
- #endif
- #include "cmGetPipes.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- #include "cmUVHandlePtr.h"
- #include "cmUVJobServerClient.h"
- namespace {
- const std::size_t kTOTAL_JOBS = 10;
- const std::size_t kTOTAL_TOKENS = 3;
- struct Job
- {
- cm::uv_timer_ptr Timer;
- };
- struct JobRunner
- {
- cm::uv_loop_ptr Loop;
- cm::optional<cmUVJobServerClient> JSC;
- std::vector<Job> Jobs;
- std::size_t NextJobIndex = 0;
- std::size_t ActiveJobs = 0;
- std::deque<std::size_t> Queue;
- bool Okay = true;
- JobRunner()
- : Jobs(kTOTAL_JOBS)
- {
- this->Loop.init(nullptr);
- this->JSC = cmUVJobServerClient::Connect(
- *this->Loop, [this]() { this->StartQueuedJob(); }, nullptr);
- if (!this->JSC) {
- std::cerr << "Failed to connect to job server.\n";
- this->Okay = false;
- }
- }
- ~JobRunner() {}
- bool Run()
- {
- if (this->Okay) {
- this->QueueNextJobs();
- uv_run(this->Loop, UV_RUN_DEFAULT);
- std::cerr << "HeldTokens: " << this->JSC->GetHeldTokens() << '\n';
- std::cerr << "NeedTokens: " << this->JSC->GetNeedTokens() << '\n';
- }
- #ifdef _WIN32
- // FIXME: Windows job server client not yet implemented.
- return true;
- #else
- return this->Okay;
- #endif
- }
- void QueueNextJobs()
- {
- std::cerr << "QueueNextJobs()\n";
- std::size_t queued = 0;
- while (queued < 2 && this->NextJobIndex < this->Jobs.size()) {
- this->QueueJob(this->NextJobIndex);
- ++this->NextJobIndex;
- ++queued;
- }
- std::cerr << "QueueNextJobs done\n";
- }
- void StartQueuedJob()
- {
- std::cerr << "StartQueuedJob()\n";
- assert(!this->Queue.empty());
- std::size_t index = this->Queue.front();
- this->Queue.pop_front();
- this->StartJob(index);
- std::cerr << "StartQueuedJob done\n";
- }
- void StartJob(std::size_t index)
- {
- cm::uv_timer_ptr& job = this->Jobs[index].Timer;
- job.init(*this->Loop, this);
- uv_timer_start(
- job,
- [](uv_timer_t* handle) {
- uv_timer_stop(handle);
- auto self = static_cast<JobRunner*>(handle->data);
- self->FinishJob();
- },
- /*timeout_ms=*/10 * (1 + (index % 3)), /*repeat_ms=*/0);
- ++this->ActiveJobs;
- std::cerr << " StartJob(" << index
- << "): Active jobs: " << this->ActiveJobs << '\n';
- if (this->ActiveJobs > kTOTAL_TOKENS) {
- std::cerr << "Started more than " << kTOTAL_TOKENS << " jobs at once!\n";
- this->Okay = false;
- return;
- }
- }
- void QueueJob(std::size_t index)
- {
- this->JSC->RequestToken();
- this->Queue.push_back(index);
- std::cerr << " QueueJob(" << index
- << "): Queue length: " << this->Queue.size() << '\n';
- }
- void FinishJob()
- {
- --this->ActiveJobs;
- std::cerr << "FinishJob: Active jobs: " << this->ActiveJobs << '\n';
- this->JSC->ReleaseToken();
- this->QueueNextJobs();
- }
- };
- bool testJobServer()
- {
- #ifdef _WIN32
- // FIXME: Windows job server client not yet implemented.
- #else
- // Create a job server pipe.
- int jobServerPipe[2];
- if (cmGetPipes(jobServerPipe) < 0) {
- std::cerr << "Failed to create job server pipe\n";
- return false;
- }
- // Write N-1 tokens to the pipe.
- std::vector<char> jobServerInit(kTOTAL_TOKENS - 1, '.');
- if (write(jobServerPipe[1], jobServerInit.data(), jobServerInit.size()) !=
- kTOTAL_TOKENS - 1) {
- std::cerr << "Failed to initialize job server pipe\n";
- return false;
- }
- // Establish the job server client context.
- // Add a bogus server spec to verify we use the last spec.
- cmSystemTools::PutEnv(cmStrCat("MAKEFLAGS=--flags-before"
- " --jobserver-auth=bogus"
- " --flags-between"
- " --jobserver-fds=",
- jobServerPipe[0], ',', jobServerPipe[1],
- " --flags-after"));
- #endif
- JobRunner jobRunner;
- return jobRunner.Run();
- }
- }
- int testUVJobServerClient(int, char** const)
- {
- bool passed = true;
- passed = testJobServer() && passed;
- return passed ? 0 : -1;
- }
|