Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .clangd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Diagnostics:
MissingIncludes: Strict
UnusedIncludes: Strict
CompileFlags:
CompilationDatabase: ./out/build/x64-debug-clang
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

# ---- Project ----

Expand Down
14 changes: 9 additions & 5 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "cl"
"CMAKE_CXX_COMPILER": "cl",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
},
"condition": {
"type": "equals",
Expand Down Expand Up @@ -105,7 +106,8 @@
{
"name": "x64-debug",
"displayName": "x64 Debug",
"description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
"description":
"Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
"inherits": "windows-base",
"architecture": {
"value": "x64",
Expand Down Expand Up @@ -139,7 +141,8 @@
{
"name": "x64-release",
"displayName": "x64 Release",
"description": "Target Windows (64-bit) with the Visual Studio development environment. (Release)",
"description":
"Target Windows (64-bit) with the Visual Studio development environment. (Release)",
"inherits": "x64-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
Expand All @@ -148,7 +151,8 @@
{
"name": "x64-release-with-debug",
"displayName": "x64 Release w/Debug",
"description": "Target Windows (64-bit) with the Visual Studio development environment. (RelWithDebInfo)",
"description":
"Target Windows (64-bit) with the Visual Studio development environment. (RelWithDebInfo)",
"inherits": "x64-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
Expand All @@ -167,4 +171,4 @@
}
}
]
}
}
2 changes: 1 addition & 1 deletion benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

project(thread-pool-benchmarks LANGUAGES CXX)

Expand Down
8 changes: 8 additions & 0 deletions benchmark/source/matrix_multiplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
#include <thread_pool/thread_pool.h>

#include <BS_thread_pool_light.hpp>
#include <chrono>
#include <concepts>
#include <cstddef>
#include <fstream>
#include <function2/function2.hpp>
#include <functional>
#include <future>
#include <riften/thiefpool.hpp>
#include <string>
#include <task_thread_pool.hpp>
#include <thread>
#include <type_traits>
#include <vector>

#include "utilities.h"

Expand Down
1 change: 1 addition & 0 deletions benchmark/source/thread_pool_scaling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <chrono>
#include <riften/thiefpool.hpp>
#include <string>
#include <thread>

inline void thread_task() {
Expand Down
2 changes: 1 addition & 1 deletion documentation/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

project(ThreadPoolDocs)

Expand Down
2 changes: 1 addition & 1 deletion examples/mandelbrot/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

project(Mandelbrot LANGUAGES CXX)

Expand Down
6 changes: 3 additions & 3 deletions examples/mandelbrot/include/fractal.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,23 @@ struct fractal_window {
/// @brief Performs smooth polynomial fitting to the given value.
rgb get_rgb_smooth(int n, int iter_max);

void save_ppm(const unsigned int &width, const unsigned int &height, std::span<rgb> colors,
void save_ppm(const unsigned int& width, const unsigned int& height, std::span<rgb> colors,
std::string_view file_name);
/**
* @brief Convert a pixel coordinate to the complex domain
* @param scr Source domain (viewing window)
* @param fr Fractal domain (real and imaginary range)
* @param c Initial complex value
*/
complex scale(const fractal_window<int> &scr, const fractal_window<double> &fr, complex c);
complex scale(const fractal_window<int>& scr, const fractal_window<double>& fr, complex c);

/**
* @brief Check if a point is in the set or escapes to infinity, return the number if iterations
* @param c Complex number value, see scale
* @param iter_max Max number of iterations
* @param func The complex function used for the fractal.
*/
int escape(complex c, int iter_max, const std::function<complex(complex, complex)> &func);
int escape(complex c, int iter_max, const std::function<complex(complex, complex)>& func);

/**
* @brief Calculate a single fractal row and returns it's color values.
Expand Down
6 changes: 3 additions & 3 deletions examples/mandelbrot/source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void mandelbrot_threadpool(int image_width, int image_height, int max_iterations
colors.reserve(source.size());

// copy data to output vector
for (auto &future : futures) {
for (auto& future : futures) {
auto data = future.get();
colors.insert(colors.end(), data.begin(), data.end());
}
Expand All @@ -56,7 +56,7 @@ void mandelbrot_threadpool(int image_width, int image_height, int max_iterations
save_ppm(source.width(), source.height(), colors, output_file_name);
}

auto main(int argc, char **argv) -> int {
auto main(int argc, char** argv) -> int {
cxxopts::Options options(*argv, "Generate a mandelbrot ppm image using a thread pool!");

int image_size;
Expand All @@ -83,7 +83,7 @@ auto main(int argc, char **argv) -> int {

mandelbrot_threadpool(image_size, image_size, max_iterations, output_file_name);

} catch (const cxxopts::exceptions::exception &e) {
} catch (const cxxopts::exceptions::exception& e) {
std::cout << "error parsing options: " << e.what() << std::endl;
exit(1);
}
Expand Down
48 changes: 25 additions & 23 deletions include/thread_pool/thread_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

#include <atomic>
#include <concepts>
#include <cstddef>
#include <deque>
#include <functional>
#include <future>
#include <memory>
#include <semaphore>
#include <thread>
#include <tuple> // std::ignore
#include <type_traits>

#ifdef __has_include
# if __has_include(<version>)
# include <version>
Expand Down Expand Up @@ -37,15 +39,15 @@ namespace dp {
requires std::invocable<InitializationFunction, std::size_t> &&
std::is_same_v<void, std::invoke_result_t<InitializationFunction, std::size_t>>
explicit thread_pool(
const unsigned int &number_of_threads = std::thread::hardware_concurrency(),
const unsigned int& number_of_threads = std::thread::hardware_concurrency(),
InitializationFunction init = [](std::size_t) {})
: tasks_(number_of_threads) {
std::size_t current_id = 0;
for (std::size_t i = 0; i < number_of_threads; ++i) {
priority_queue_.push_back(size_t(current_id));
try {
threads_.emplace_back([&, id = current_id,
init](const std::stop_token &stop_tok) {
init](const std::stop_token& stop_tok) {
// invoke the init function on the thread
try {
std::invoke(init, id);
Expand Down Expand Up @@ -124,8 +126,8 @@ namespace dp {
}

/// thread pool is non-copyable
thread_pool(const thread_pool &) = delete;
thread_pool &operator=(const thread_pool &) = delete;
thread_pool(const thread_pool&) = delete;
thread_pool& operator=(const thread_pool&) = delete;

/**
* @brief Enqueue a task into the thread pool that returns a result.
Expand All @@ -138,7 +140,7 @@ namespace dp {
* @return A std::future<ReturnType> that can be used to retrieve the returned value.
*/
template <typename Function, typename... Args,
typename ReturnType = std::invoke_result_t<Function &&, Args &&...>>
typename ReturnType = std::invoke_result_t<Function&&, Args&&...>>
requires std::invocable<Function, Args...>
[[nodiscard]] std::future<ReturnType> enqueue(Function f, Args... args) {
#ifdef __cpp_lib_move_only_function
Expand Down Expand Up @@ -205,22 +207,22 @@ namespace dp {
*/
template <typename Function, typename... Args>
requires std::invocable<Function, Args...>
void enqueue_detach(Function &&func, Args &&...args) {
enqueue_task(std::move([f = std::forward<Function>(func),
... largs =
std::forward<Args>(args)]() mutable -> decltype(auto) {
// suppress exceptions
try {
if constexpr (std::is_same_v<void,
std::invoke_result_t<Function &&, Args &&...>>) {
std::invoke(f, largs...);
} else {
// the function returns an argument, but can be ignored
std::ignore = std::invoke(f, largs...);
void enqueue_detach(Function&& func, Args&&... args) {
enqueue_task(
std::move([f = std::forward<Function>(func),
... largs = std::forward<Args>(args)]() mutable -> decltype(auto) {
// suppress exceptions
try {
if constexpr (std::is_same_v<void,
std::invoke_result_t<Function&&, Args&&...>>) {
std::invoke(f, largs...);
} else {
// the function returns an argument, but can be ignored
std::ignore = std::invoke(f, largs...);
}
} catch (...) {
}
} catch (...) {
}
}));
}));
}

/**
Expand Down Expand Up @@ -251,7 +253,7 @@ namespace dp {
*/
size_t clear_tasks() {
size_t removed_task_count{0};
for (auto &task_list : tasks_) {
for (auto& task_list : tasks_) {
removed_task_count += task_list.tasks.clear();
}
in_flight_tasks_.fetch_sub(removed_task_count, std::memory_order_release);
Expand All @@ -262,7 +264,7 @@ namespace dp {

private:
template <typename Function>
void enqueue_task(Function &&f) {
void enqueue_task(Function&& f) {
auto i_opt = priority_queue_.copy_front_and_rotate_to_back();
if (!i_opt.has_value()) {
// would only be a problem if there are zero threads
Expand Down
1 change: 1 addition & 0 deletions include/thread_pool/thread_safe_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <deque>
#include <mutex>
#include <optional>
#include <tuple> // std::ignore

namespace dp {
/**
Expand Down
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

project(thread-pool-tests LANGUAGES CXX)

Expand Down