Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
BS_thread_pool_test.cpp File Reference

BS::thread_pool: a fast, lightweight, modern, and easy-to-use C++17/C++20/C++23 thread pool library. This program tests all aspects of the library, but is not needed in order to use the library. More...

#include <algorithm>
#include <array>
#include <atomic>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <functional>
#include <future>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <mutex>
#include <numeric>
#include <optional>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <thread>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "BS_thread_pool.hpp"
Include dependency graph for BS_thread_pool_test.cpp:

Macros

#define BS_THREAD_POOL_TEST_VERSION   5, 1, 0
 
#define UNPACK_2_BYTES(value)   static_cast<std::uint8_t>(value), static_cast<std::uint8_t>((value) >> 8)
 
#define UNPACK_4_BYTES(value)   static_cast<std::uint8_t>(value), static_cast<std::uint8_t>((value) >> 8), static_cast<std::uint8_t>((value) >> 16), static_cast<std::uint8_t>((value) >> 24)
 

Functions

int main (int argc, char *argv[])
 

Variables

constexpr bool using_import_std = false
 

Detailed Description

BS::thread_pool: a fast, lightweight, modern, and easy-to-use C++17/C++20/C++23 thread pool library. This program tests all aspects of the library, but is not needed in order to use the library.

██████ ███████ ████████ ██ ██ ██████ ███████ █████ ██████ ██████ ██████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ███████ ██ ███████ ██████ █████ ███████ ██ ██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ███████ ██ ██ ██ ██ ██ ███████ ██ ██ ██████ ███████ ██ ██████ ██████ ███████

Author
Barak Shoshany (barak.nosp@m.sh@g.nosp@m.mail..nosp@m.com) (https://baraksh.com/)
Version
5.1.0
Date
2026-01-03

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)
3977{
3978#ifdef __cpp_exceptions
3979 try
3980 {
3981#endif
3982 // Disable ANSI colors if the environment variable `NO_COLOR` is set.
3983 no_color = (std::getenv("NO_COLOR") != nullptr); // NOLINT(concurrency-mt-unsafe)
3984
3985 // If the file default_args.txt exists in either this folder or the parent folder, read the default arguments from it (space separated in a single line). Otherwise, use the built-in defaults. This is useful when debugging.
3986 std::map<std::string, bool> defaults;
3987 std::ifstream default_args_file("default_args.txt");
3988 if (!default_args_file.is_open())
3989 default_args_file.open("../default_args.txt");
3990 if (default_args_file.is_open())
3991 {
3992 std::string line;
3993 std::getline(default_args_file, line);
3994 std::istringstream iss(line);
3995 std::string arg;
3996 while (iss >> arg)
3997 defaults[arg] = true;
3998 default_args_file.close();
3999 }
4000 else
4001 {
4002 defaults = {{"help", false}, {"stdout", true}, {"log", true}, {"tests", true}, {"deadlock", false}, {"benchmarks", true}, {"plot", false}, {"save", false}};
4003 }
4004
4005 // Parse the command line arguments.
4006 arg_parser args(argc, argv);
4007 args.add_argument("help", "Show this help message and exit.", defaults["help"]);
4008 args.add_argument("stdout", "Print to the standard output.", defaults["stdout"]);
4009 args.add_argument("log", "Print to a log file.", defaults["log"]);
4010 args.add_argument("tests", "Perform standard tests.", defaults["tests"]);
4011 args.add_argument("deadlock", "Perform long deadlock tests.", defaults["deadlock"]);
4012 args.add_argument("benchmarks", "Perform full Mandelbrot plot benchmarks.", defaults["benchmarks"]);
4013 args.add_argument("plot", "Perform quick Mandelbrot plot benchmarks.", defaults["plot"]);
4014 args.add_argument("save", "Save the Mandelbrot plot to a file.", defaults["save"]);
4015
4016 if (args.size() > 0)
4017 {
4018 if (args["help"] || !args.verify())
4019 {
4020 show_intro();
4021 args.show_help();
4022 return 0;
4023 }
4024 if (!args["stdout"] && !args["log"])
4025 {
4026 show_intro();
4027 args.show_help();
4028 logln_ansi(ansi_error, "\nERROR: No output stream specified! Please enter one or more of: log, stdout. Aborting.");
4029 return 0;
4030 }
4031 if (!args["benchmarks"] && !args["deadlock"] && !args["plot"] && !args["tests"])
4032 {
4033 show_intro();
4034 args.show_help();
4035 logln_ansi(ansi_error, "\nERROR: No tests or benchmarks requested! Please enter one or more of: benchmarks, deadlock, plot, tests. Aborting.");
4036 return 0;
4037 }
4038 }
4039
4040 // A stream object used to access the log file.
4041 std::ofstream log_file;
4042
4043 sync_log.remove_stream(std::cout);
4044 if (args["log"])
4045 {
4046 // Extract the name of the executable file, or use a default value if it is not available.
4047 const std::string_view executable = args.get_executable();
4048 const std::size_t last_slash = executable.find_last_of("/\\") + 1;
4049 std::string exe_file(executable.substr(last_slash, executable.find('.', last_slash) - last_slash));
4050 if (exe_file.empty())
4051 exe_file = "BS_thread_pool_test";
4052 // Create a log file using the name of the executable, followed by the current date and time.
4053 const std::string log_filename = exe_file + "-" + get_time() + ".log";
4054 log_file.open(log_filename);
4055 if (log_file.is_open())
4056 {
4057 logln_ansi(ansi_info, "Generating log file: ", log_filename);
4058 sync_log.add_stream(log_file);
4059 }
4060 else
4061 {
4062 logln_ansi(ansi_error, "ERROR: Could not create a log file.");
4063 return 1;
4064 }
4065 }
4066
4067 use_stdout = args["stdout"];
4068 use_log = args["log"];
4069
4070 show_intro();
4071
4072 if (args["tests"])
4073 {
4074 print_header("Checking the constructor:");
4075 check_constructor();
4076
4077 print_header("Checking reset():");
4078 check_reset();
4079
4080 print_header("Checking detach_task() and submit_task():");
4081 check_task("detach_task()");
4082 check_task("submit_task()");
4083
4084 print_header("Checking submission of member functions as tasks:");
4085 check_member_function();
4086 check_member_function_within_object();
4087
4088 print_header("Checking submission of different callable types:");
4089 check_callables();
4090
4091 print_header("Checking wait(), wait_for(), and wait_until():");
4092 check_wait();
4093 check_wait_blocks();
4094 check_wait_for();
4095 check_wait_until();
4096 check_wait_multiple_deadlock();
4097#ifdef __cpp_exceptions
4098 check_wait_self_deadlock();
4099
4100 print_header("Checking exception handling:");
4101 check_exceptions_submit();
4102 check_exceptions_multi_future();
4103#else
4104 logln_ansi(ansi_info, "NOTE: Exceptions are disabled, skipping wait deadlock check and exception handling tests.");
4105#endif
4106
4107 print_header("Checking detach_loop() and submit_loop():");
4108 check_loop();
4109
4110 print_header("Checking detach_blocks() and submit_blocks():");
4111 check_blocks();
4112
4113 print_header("Checking detach_sequence() and submit_sequence():");
4114 check_sequence();
4115
4116 print_header("Checking task monitoring:");
4117 check_task_monitoring();
4118
4119 print_header("Checking pausing:");
4120 check_pausing();
4121
4122 print_header("Checking purge():");
4123 check_purge();
4124
4125 print_header("Checking parallelized vector operations:");
4126 check_vectors();
4127
4128 print_header("Checking task priority:");
4129 check_priority();
4130
4131 print_header("Checking thread initialization/cleanup functions and BS::this_thread:");
4132 check_init();
4133 check_cleanup();
4134 check_get_pool();
4135
4136 print_header("Checking that parallelized tasks do not get copied:");
4137 check_copy_all();
4138
4139 print_header("Checking that shared pointers are correctly shared:");
4140 check_shared_ptr_all();
4141
4142 print_header("Checking that tasks are destructed immediately after running:");
4143 check_task_destruct();
4144
4145 print_header("Checking BS::common_index_type:");
4146 check_common_index_type();
4147
4148#ifdef BS_THREAD_POOL_NATIVE_EXTENSIONS
4149 print_header("Checking native extensions:");
4150 #ifndef _WIN32
4151 if ((args["benchmarks"] || args["plot"]) && !BS::set_os_process_priority(BS::os_process_priority::realtime))
4152 {
4153 logln_ansi(ansi_info, "NOTE: Skipping process/thread priority checks since the test is running on Linux/macOS without root privileges and benchmarks are enabled. On Linux/macOS, if priorities are decreased, they cannot be increased back to normal without root privileges, so the process will be stuck on the lowest priority, and the benchmarks will be unreliable.\n");
4154 }
4155 else
4156 #endif
4157 {
4158 // Note: We have to check thread priorities first, because the check for process priorities lowers the priority of the process to the lowest level, and on Linux, if not running as root, we can only lower the priority, not raise it, so the process gets stuck on the lowest priority. Since the thread priorities cannot be set to higher than the process priorities, this means the thread priorities will also be stuck on the lowest priority, and the test will fail.
4159 check_os_thread_priorities();
4160 logln();
4161 check_os_process_priorities();
4162 logln();
4163 }
4164 check_os_thread_names();
4165 logln();
4166 #if defined(_WIN32) || defined(__linux__)
4167 check_os_thread_affinity();
4168 logln();
4169 check_os_process_affinity();
4170 #else
4171 logln_ansi(ansi_info, "NOTE: macOS does not support affinity, skipping the corresponding test.");
4172 #endif
4173#else
4174 logln_ansi(ansi_info, "NOTE: Native extensions disabled, skipping the corresponding test.");
4175#endif
4176 }
4177
4178 if (args["deadlock"])
4179 {
4180 print_header("Checking for deadlocks:");
4181 logln("Checking for destruction deadlocks...");
4182 check_deadlock(
4183 []
4184 {
4185 BS::thread_pool temp_pool;
4186 temp_pool.detach_task([] {});
4187 });
4188 logln("Checking for reset deadlocks...");
4189 BS::thread_pool temp_pool;
4190 check_deadlock(
4191 [&temp_pool]
4192 {
4193 temp_pool.reset();
4194 });
4195 }
4196
4197 if (test_results::tests_failed > 0)
4198 {
4199 print_header("FAILURE: Passed " + std::to_string(test_results::tests_succeeded) + " checks, but failed " + std::to_string(test_results::tests_failed) + "!", '+', ansi_error);
4200 logln_ansi(ansi_error, "\nPlease submit a bug report at https://github.com/bshoshany/thread-pool/issues including the exact specifications of your system (OS, CPU, compiler, etc.) and the generated log file.");
4201 log_file.close();
4202 return static_cast<int>(test_results::tests_failed);
4203 }
4204
4205 if (test_results::tests_succeeded > 0)
4206 print_header("SUCCESS: Passed all " + std::to_string(test_results::tests_succeeded) + " checks!", '+', ansi_success);
4207
4208 if (args["benchmarks"] || args["plot"])
4209 check_performance(args["benchmarks"], args["plot"], args["save"]);
4210
4211 log_file.close();
4212 return 0;
4213#ifdef __cpp_exceptions
4214 }
4215 catch (const std::exception& e)
4216 {
4217 logln_ansi(ansi_error, "ERROR: Tests failed due to exception: ", e.what());
4218 return 1;
4219 }
4220#endif
4221}
A fast, lightweight, modern, and easy-to-use C++17/C++20/C++23 thread pool class.
Definition BS_thread_pool.hpp:1429
void detach_task(F &&task, const priority_t priority=0)
Submit a function with no arguments and no return value into the task queue, with the specified prior...
Definition BS_thread_pool.hpp:1627
void reset()
Reset the pool with the default number of threads (as if constructed with the default constructor)....
Definition BS_thread_pool.hpp:1744
void line(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)