From e528cd795fb33775f326af87628370d7798fab10 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 20 Nov 2023 18:49:50 -0500 Subject: cmCTestMultiProcessHandler: Start new tests asynchronously When a test finishes, defer starting new tests until the next loop iteration. That way, if multiple tests finish in a single loop iteration, we can free all of their resources first, and then start a new batch of tests. --- Source/CTest/cmCTestMultiProcessHandler.cxx | 17 +++++++++++++++-- Source/CTest/cmCTestMultiProcessHandler.h | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index bb6bb9d..a673370 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -128,12 +128,14 @@ bool cmCTestMultiProcessHandler::Complete() void cmCTestMultiProcessHandler::InitializeLoop() { this->Loop.init(); + this->StartNextTestsOnIdle_.init(*this->Loop, this); this->StartNextTestsOnTimer_.init(*this->Loop, this); } void cmCTestMultiProcessHandler::FinalizeLoop() { this->StartNextTestsOnTimer_.reset(); + this->StartNextTestsOnIdle_.reset(); this->Loop.reset(); } @@ -146,7 +148,7 @@ void cmCTestMultiProcessHandler::RunTests() this->TestHandler->SetMaxIndex(this->FindMaxIndex()); this->InitializeLoop(); - this->StartNextTests(); + this->StartNextTestsOnIdle(); uv_run(this->Loop, UV_RUN_DEFAULT); this->FinalizeLoop(); @@ -468,6 +470,7 @@ void cmCTestMultiProcessHandler::StartNextTests() { // One or more events may be scheduled to call this method again. // Since this method has been called they are no longer needed. + this->StartNextTestsOnIdle_.stop(); this->StartNextTestsOnTimer_.stop(); if (this->PendingTests.empty() || this->CheckStopTimePassed() || @@ -624,6 +627,16 @@ void cmCTestMultiProcessHandler::StartNextTests() } } +void cmCTestMultiProcessHandler::StartNextTestsOnIdle() +{ + // Start more tests on the next loop iteration. + this->StartNextTestsOnIdle_.start([](uv_idle_t* idle) { + uv_idle_stop(idle); + auto* self = static_cast(idle->data); + self->StartNextTests(); + }); +} + void cmCTestMultiProcessHandler::StartNextTestsOnTimer() { // Wait between 1 and 5 seconds before trying again. @@ -682,7 +695,7 @@ void cmCTestMultiProcessHandler::FinishTestProcess( runner.reset(); if (started) { - this->StartNextTests(); + this->StartNextTestsOnIdle(); } } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index cac35e3..cc230e7 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -130,6 +130,7 @@ protected: void ErasePendingTest(int index); void FinishTestProcess(std::unique_ptr runner, bool started); + void StartNextTestsOnIdle(); void StartNextTestsOnTimer(); void RemoveTest(int index); @@ -207,6 +208,7 @@ protected: unsigned long TestLoad; unsigned long FakeLoadForTesting; cm::uv_loop_ptr Loop; + cm::uv_idle_ptr StartNextTestsOnIdle_; cm::uv_timer_ptr StartNextTestsOnTimer_; cmCTestTestHandler* TestHandler; cmCTest* CTest; -- cgit v0.12