From 90af651f24b44df436c8f295d16689428a4d9f0d Mon Sep 17 00:00:00 2001 From: q66 Date: Wed, 29 Mar 2017 20:41:53 +0200 Subject: [PATCH] document thread pool --- ostd/concurrency.hh | 5 +++- ostd/coroutine.hh | 10 +++---- ostd/thread_pool.hh | 65 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/ostd/concurrency.hh b/ostd/concurrency.hh index 8c5487a..1840ebc 100644 --- a/ostd/concurrency.hh +++ b/ostd/concurrency.hh @@ -1,6 +1,6 @@ /** @defgroup Concurrency * - * @brief Concurrent task execution support. + * @brief Concurrent/parallel task execution support and related APIs. * * OctaSTD provides an elaborate concurrency system that covers multiple * schedulers with different characteristics as well as different ways to @@ -27,6 +27,9 @@ * * See the examples provided with the library for further information. * + * It also implements all sorts of utilities for dealing with parallel + * programs and synchronization, including a thread pool and other facilities. + * * @{ */ diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 189d980..78243ae 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -262,7 +262,7 @@ protected: * It's therefore necessary for @p C to give the context access to its * `resume_call()` method, typically by making coroutine_context a friend. * - * @param sa The stack allocator used to allocate the stack. + * @param[in] sa The stack allocator used to allocate the stack. * @tparam C The coroutine type that inherits from the context class. */ template @@ -739,8 +739,8 @@ public: * * Otherwise creates a context using the provided stack allocator. * - * @param func The function to use. - * @param sa The stack allocator, defaults to a default_stack. + * @param[in] func The function to use. + * @param[in] sa The stack allocator, defaults to a default_stack. * * @throws Whatever an `std::function` constructor could throw. */ @@ -988,8 +988,8 @@ public: * Otherwise creates a context using the provided stack allocator * and then resumes the generator, making it get a value (or die). * - * @param func The function to use. - * @param sa The stack allocator, defaults to a default_stack. + * @param[in] func The function to use. + * @param[in] sa The stack allocator, defaults to a default_stack. * * @throws Whatever an `std::function` constructor could throw. */ diff --git a/ostd/thread_pool.hh b/ostd/thread_pool.hh index ada48b2..e7f45d4 100644 --- a/ostd/thread_pool.hh +++ b/ostd/thread_pool.hh @@ -1,6 +1,15 @@ -/* A thread pool that can be used standalone or within a more elaborate module. +/** @addtogroup Concurrency + * @{ + */ + +/** @file thread_pool.hh * - * This file is part of OctaSTD. See COPYING.md for futher information. + * @brief A pool of threads with workers. + * + * This file implements a regular thread pool with worker threads. It does + * not do any elaborate stuff with coroutines or task scheduling. + * + * @copyright See COPYING.md in the project tree for further information. */ #ifndef OSTD_THREAD_POOL_HH @@ -19,6 +28,10 @@ namespace ostd { +/** @addtogroup Concurrency + * @{ + */ + namespace detail { struct tpool_func_base { tpool_func_base() {} @@ -87,25 +100,43 @@ namespace detail { }; } +/** @brief A thread pool. + * + * A simple thread pool that lets you start a specified number of threads + * and queue tasks onto them. No elaborate scheduling is performed, tasks + * are called on threads as they become available and are assumed completed + * once they return. + */ struct thread_pool { + /** @brief Starts the thread pool. + * + * Creates the threads and marks the pool as running. The number of + * threads defaults to the number of hardware threads in your system. + * + * @param[in] size The number of threads to use. + */ void start(size_t size = std::thread::hardware_concurrency()) { p_running = true; auto tf = [this]() { thread_run(); }; for (size_t i = 0; i < size; ++i) { - std::thread tid{tf}; - if (!tid.joinable()) { - throw std::runtime_error{"thread_pool worker failed"}; - } - p_thrs.push_back(std::move(tid)); + p_thrs.push_back(std::thread{tf}); } } + /** Calls destroy(). */ ~thread_pool() { destroy(); } + /** @brief Destroys the thread pool. + * + * If the pool is not running, this method simply returns. Otherwise + * it notifies all threads to run any remaining queued tasks and + * proceeds to wait for every thread to finish, notifying the rest + * every time after a thread successfully exits. + */ void destroy() { { std::lock_guard l{p_lock}; @@ -121,6 +152,22 @@ struct thread_pool { } } + /** @brief Queues a new task for execution. + * + * Queues the given function for execution. Any extra passed parameters + * are bound to the function first before queuing. It also lets you + * retrieve the return value of the task at later point, via the + * returned future. + * + * The function's argument types and the provided arguments must match. + * + * @param[in] func The function to queue. + * @param[in] args A parameter pack matching the function's arguments. + * + * @returns A future to the return type of the task. + * + * @throws std::runtime_error if the pool is not running. + */ template auto push(F &&func, A &&...args) -> std::future> @@ -170,6 +217,10 @@ private: bool p_running = false; }; +/** @} */ + } /* namespace ostd */ +/** @} */ + #endif