From 05d74eaaa6f3988cbb97241b2842e78661d735a8 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Sun, 28 Apr 2024 18:48:58 +0530 Subject: [PATCH] Add a test for Threads::Task. --- tests/multithreading/task_17.cc | 72 +++++++++++++++++++++++++++++ tests/multithreading/task_17.output | 13 ++++++ 2 files changed, 85 insertions(+) create mode 100644 tests/multithreading/task_17.cc create mode 100644 tests/multithreading/task_17.output diff --git a/tests/multithreading/task_17.cc b/tests/multithreading/task_17.cc new file mode 100644 index 0000000000..c23dd0b8c0 --- /dev/null +++ b/tests/multithreading/task_17.cc @@ -0,0 +1,72 @@ +// ------------------------------------------------------------------------ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (C) 2016 - 2023 by the deal.II authors +// +// This file is part of the deal.II library. +// +// Part of the source code is dual licensed under Apache-2.0 WITH +// LLVM-exception OR LGPL-2.1-or-later. Detailed license information +// governing the source code and code contributions can be found in +// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II. +// +// ------------------------------------------------------------------------ + + +// Allow only 2 threads (= concurrently running tasks) but create 3 +// and make sure each can wait for the next to finish. This requires +// that in the underlying implementation, when we wait for a task we +// go back into the scheduler and execute more tasks. In other words, +// waiting for another task doesn't just block the current task (which +// would lead to deadlocks because we're already running the maximum +// number of current tasks) but gives the scheduler the opportunity to +// work on other tasks. + + +#include + +#include "../tests.h" + +void +bottom() +{ + deallog << " Starting task at the bottom" << std::endl; + deallog << " ... ... ..." << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + deallog << " Ending task at the bottom" << std::endl; +} + +void +middle() +{ + deallog << " Starting task in the middle" << std::endl; + auto t = Threads::new_task([]() { bottom(); }); + deallog << " Waiting for sub-task in the middle" << std::endl; + t.join(); + deallog << " Ending task in the middle" << std::endl; +} + +void +top() +{ + deallog << " Starting task at the top" << std::endl; + auto t = Threads::new_task([]() { middle(); }); + deallog << " Waiting for sub-task at the top" << std::endl; + t.join(); + deallog << " Ending task at the top" << std::endl; +} + + +int +main() +{ + initlog(); + + MultithreadInfo::set_thread_limit(2); + + deallog << "Starting task in main()" << std::endl; + auto t = Threads::new_task([]() { top(); }); + deallog << "Waiting for task in main" << std::endl; + t.join(); + deallog << "Done in main" << std::endl; +} diff --git a/tests/multithreading/task_17.output b/tests/multithreading/task_17.output new file mode 100644 index 0000000000..2155c5bc5b --- /dev/null +++ b/tests/multithreading/task_17.output @@ -0,0 +1,13 @@ + +DEAL::Starting task in main() +DEAL::Waiting for task in main +DEAL:: Starting task at the top +DEAL:: Waiting for sub-task at the top +DEAL:: Starting task in the middle +DEAL:: Waiting for sub-task in the middle +DEAL:: Starting task at the bottom +DEAL:: ... ... ... +DEAL:: Ending task at the bottom +DEAL:: Ending task in the middle +DEAL:: Ending task at the top +DEAL::Done in main -- 2.39.5