HSLL::ThreadPool - 高并发任务调度线程池

ThreadPool - 高并发任务调度线程池

HSLL::ThreadPool 是基于HSLL::BlockQueue实现的弹性任务调度系统,采用批量处理优化和智能任务分发机制。提供多种任务提交模式,适用于高吞吐量、低延迟的并行计算场景。


依赖于HSLL::BlockQueue :BlockQueue - 高效线程安全阻塞队列

您的star是对该项目的肯定

核心特性

1. 智能任务调度

  • 双模式工作线程
    • 单任务模式:逐条处理保证最低延迟
    • 批量模式:单次处理最多batchSize个任务,提升吞吐量
  • 自适应负载均衡:基于BlockQueue实现自动背压控制

2. 多样化提交接口

提交方式非阻塞无限等待超时等待
单任务提交append()wait_append()wait_append(timeout)
单任务原位构造emplace()wait_emplace()wait_emplace(timeout)
批量提交appendBulk()wait_appendBulk()wait_appendBulk(timeout)
批量原位构造emplaceBulk()wait_emplaceBulk()wait_emplaceBulk(timeout)

3. 高效资源管理

  • 预分配任务队列:初始化时固定队列容量,消除运行时内存分配
  • 零拷贝任务传递:支持原位构造和完美转发
  • 优雅关闭机制:立即停止信号+队列耗尽处理

使用示例

// 定义任务类型
class ComputeTask {
public:
    ComputeTask(int param, float factor) : data(param * factor) {}
    
    void execute() {
        // 执行计算任务
        result = std::sqrt(data);
    }

private:
    double data;
    double result;
};

// 初始化线程池(队列容量4096,8工作线程,批量大小16)
HSLL::ThreadPool<ComputeTask> pool;
if (!pool.init(4096, 8, 16)) {
    throw std::runtime_error("Thread pool init failed");
}

// 提交单个任务(原位构造)
pool.emplace(100, 2.71828f);

// 批量提交参数包
struct TaskParams {
    int base;
    float scale;
};
TaskParams params[32];
/* 初始化参数数组... */
unsigned sent = pool.emplaceBulk(params, 32);

// 动态任务提交
auto task = ComputeTask(42, 3.14f);
pool.wait_append(std::move(task));

// 优雅关闭
pool.exit();

接口规范

核心方法

方法说明
bool init(queueSize, threadNum, batchSize=1)初始化线程池(必须先调用)
emplace()/emplaceBulk()原位构造任务,避免拷贝
append()/appendBulk()提交已构造任务到队列
wait_*系列阻塞等待直到任务提交成功或超时
exit()停止接收新任务并等待所有任务完成

模板要求

  • 任务类型T必须提供:
    • 可调用的execute()方法
    • 匹配构造函数(emplace系列使用)
    • 可移动构造(append系列使用)

内部工作机制

任务处理流程

+---------------+     +----------------+     +---------------+
|  Task         |     | BlockingQueue  |     | Worker Thread |
|  Submitters   | --> | (线程安全缓冲) | --> | (批量执行器)  |
+---------------+     +----------------+     +---------------+

工作线程逻辑

void worker() {
    if (batchSize == 1) {
        // 单任务处理模式
        while(获取任务成功) {
            执行任务 -> 销毁任务
        }
    } else {
        // 批量处理模式
        T* bulkBuffer = 预分配批量内存;
        while(获取批量任务成功) {
            for(每个任务) {
                执行任务 -> 销毁任务
            }
        }
    }
}

注意事项

  1. 初始化约束

    • 必须成功调用init()后才能提交任务
    • batchSize必须≥1且≤队列容量
  2. 生命周期管理

    • 任务对象在入队时构造,执行后立即析构
    • 线程池析构时会自动调用exit()
  3. 线程安全

    • 所有公共方法线程安全
    • 不同线程池实例之间无资源竞争
  4. 特殊限制

    • 任务类型禁止抛出构造/析构异常
    • execute()方法不应长时间阻塞
  5. 资源释放

    • exit()会等待所有线程的调用返回
    • 强制终止需外部干预机制

源码

#ifndef HSLL_THREADPOOL
#define HSLL_THREADPOOL

#include <vector>
#include <thread>
#include <atomic>
#include "BlockQueue.hpp"

namespace HSLL
{

    /**
     * @brief Thread pool class for managing worker threads and task execution
     * @tparam T Type of tasks to be processed by the thread pool
     */
    template <class T>
    class ThreadPool
    {
    private:
        unsigned int batchSize; 
        BlockQueue<T> taskQueue;
        std::atomic<unsigned int> count;
        std::atomic<unsigned int> error;
        std::vector<std::thread> workers;

    public:
        ThreadPool() = default;

        /**
         * @brief Initialize the thread pool with specified parameters
         * @param queueSize Maximum capacity of the task queue
         * @param threadNum Number of worker threads to create
         * @param batchSize Number of tasks to process in batch (default=1)
         * @return true if initialization succeeded, false otherwise
         * @note Batch size must be greater than 0 for successful initialization
         */
        bool init(unsigned int queueSize, unsigned int threadNum, unsigned int batchSize = 1)
        {
            if (batchSize == 0)
                return false;

            this->batchSize = batchSize;
            count = 0;
            error = 0;

            if (!taskQueue.init(queueSize))
                return false;

            for (unsigned i = 0; i < threadNum; ++i)
                workers.emplace_back(&ThreadPool::worker, this);

            while (count != threadNum)
                std::this_thread::sleep_for(std::chrono::milliseconds(1));

            if (error)
            {
                exit();
                return false;
            }

            return true;
        }

        /**
         * @brief Non-blocking element emplacement with perfect forwarding
         * @tparam Args Types of arguments to forward to element constructor
         * @param args Arguments to forward to element constructor
         * @return true if element was emplaced, false if queue was full
         * @details Constructs element in-place at the tail of the queue using
         *          perfect forwarding. Notifies consumers if successful.
         */
        template <typename... Args>
        bool emplace(Args &&...args)
        {
            return taskQueue.emplace(std::forward<Args>(args)...);
        }

        /**
         * @brief Blocking element emplacement with indefinite wait
         * @tparam Args Types of arguments to forward to element constructor
         * @param args Arguments to forward to element constructor
         * @return true if element was emplaced, false if queue was stopped
         * @details Waits until queue has space or is stopped. Constructs element
         *          in-place and notifies consumers upon success.
         */
        template <typename... Args>
        bool wait_emplace(Args &&...args)
        {
            return taskQueue.wait_emplace(std::forward<Args>(args)...);
        }

        /**
         * @brief Blocking element emplacement with timeout
         * @tparam Rep Chrono duration representation type
         * @tparam Period Chrono duration period type
         * @tparam Args Types of arguments to forward to element constructor
         * @param timeout Maximum duration to wait for space
         * @param args Arguments to forward to element constructor
         * @return true if element was emplaced, false on timeout or stop
         * @details Waits up to specified duration for space. Constructs element
         *          in-place if space becomes available and notifies consumers.
         */
        template <class Rep, class Period, typename... Args>
        bool wait_emplace(const std::chrono::duration<Rep, Period> &timeout, Args &&...args)
        {
            return taskQueue.wait_emplace(timeout, std::forward<Args>(args)...);
        }

        /**
         * @brief Non-blocking bulk default construction
         * @param count Number of default-constructed elements to create
         * @return Actual number of elements successfully created
         * @details Uses TYPE's default constructor. Fails immediately if queue
         *          lacks sufficient space. Notifies consumers appropriately.
         */
        unsigned int emplaceBulk(unsigned int count)
        {
            return taskQueue.emplaceBulk(count);
        }

        /**
         * @brief Non-blocking bulk construction from parameters array
         * @tparam PACKAGE Type of construction arguments for TYPE
         * @param packages Pointer to array of construction arguments
         * @param count Number of elements to construct
         * @return Actual number of elements successfully created
         * @details Constructs elements using TYPE's constructor that accepts PACKAGE.
         *          Copies arguments from input array. Notifies consumers with
         *          appropriate signal (single/multi) based on inserted quantity.
         * @note TYPE must have either TYPE(PACKAGE&) or TYPE(PACKAGE) constructor
         */
        template <typename PACKAGE>
        unsigned int emplaceBulk(PACKAGE *packages, unsigned int count)
        {
            return taskQueue.emplaceBulk(packages, count);
        }

        /**
         * @brief Blocking bulk default construction with wait
         * @param count Number of default-constructed elements to create
         * @return Actual number of elements created before stop/full
         * @details Waits for space using TYPE's default constructor. Processes
         *          maximum available capacity when awakened. Notifies consumers
         *          based on inserted quantity.
         */
        unsigned int wait_emplaceBulk(unsigned int count)
        {
            return taskQueue.wait_emplaceBulk(count);
        }

        /**
         * @brief Blocking bulk construction from parameters array
         * @tparam PACKAGE Type of construction arguments for TYPE
         * @param packages Pointer to construction arguments array
         * @param count Number of elements to construct
         * @return Actual number of elements created before stop/full
         * @details Waits indefinitely until space becomes available. Constructs
         *          elements using TYPE's constructor that accepts PACKAGE arguments.
         *          Returns immediately if queue is stopped.
         * @note Requires TYPE(PACKAGE&) or TYPE(PACKAGE) constructor
         */
        template <typename PACKAGE>
        unsigned int wait_emplaceBulk(PACKAGE *packages, unsigned int count)
        {
            return taskQueue.wait_emplaceBulk(packages, count);
        }

        /**
         * @brief Timed bulk default construction
         * @tparam Rep Chrono duration representation type
         * @tparam Period Chrono duration period type
         * @param count Maximum elements to default-construct
         * @param timeout Maximum wait duration
         * @return Actual number of elements created
         * @details Combines timed wait with default construction. Processes
         *          maximum possible elements if space becomes available.
         *          Notifies consumers based on inserted quantity.
         */
        template <class Rep, class Period>
        unsigned int wait_emplaceBulk(unsigned int count,
                                      const std::chrono::duration<Rep, Period> &timeout)
        {
            return taskQueue.wait_emplaceBulk(count, timeout);
        }

        /**
         * @brief Timed bulk construction from parameters array
         * @tparam PACKAGE Type of construction arguments
         * @tparam Rep Chrono duration representation type
         * @tparam Period Chrono duration period type
         * @param packages Construction arguments array
         * @param count Maximum elements to construct
         * @param timeout Maximum wait duration
         * @return Actual number of elements constructed
         * @details Waits up to timeout duration for space. Constructs elements
         *          using TYPE's PACKAGE-accepting constructor. Returns immediately
         *          on timeout or queue stop.
         * @note TYPE must be constructible from PACKAGE arguments
         */
        template <typename PACKAGE, class Rep, class Period>
        unsigned int wait_emplaceBulk(PACKAGE *packages, unsigned int count,
                                      const std::chrono::duration<Rep, Period> &timeout)
        {
            return taskQueue.wait_emplaceBulk(packages, count, timeout);
        }

        /**
         * @brief Append a single task to the queue
         * @tparam U Forward reference type for task object
         * @param task Task object to be added
         * @return true if task was successfully added, false otherwise
         */
        template <typename U>
        bool append(U &&task)
        {
            return taskQueue.push(std::forward<U>(task));
        }

        /**
         * @brief Append multiple tasks to the queue in bulk
         * @param tasks Pointer to array of tasks
         * @param count Number of tasks in the array
         * @return Number of tasks successfully added
         */
        unsigned int append_bulk(T *tasks, unsigned int count)
        {
            return taskQueue.pushBulk(tasks, count);
        }

        /**
         * @brief Wait and append a single task to the queue
         * @tparam U Forward reference type for task object
         * @param task Task object to be added
         * @return true if task was successfully added before timeout, false otherwise
         */
        template <typename U>
        bool wait_append(U &&task)
        {
            return taskQueue.wait_push(std::forward<U>(task));
        }

        /**
         * @brief Wait and append a single task with timeout
         * @tparam U Forward reference type for task object
         * @tparam Rep Time unit type for duration
         * @tparam Period Time interval type for duration
         * @param task Task object to be added
         * @param timeout Maximum wait duration
         * @return true if task was successfully added before timeout, false otherwise
         */
        template <typename U, class Rep, class Period>
        bool wait_append(U &&task, const std::chrono::duration<Rep, Period> &timeout)
        {
            return taskQueue.wait_push(std::forward<U>(task), timeout);
        }

        /**
         * @brief Wait and append multiple tasks in bulk
         * @param tasks Pointer to array of tasks
         * @param count Number of tasks in the array
         * @return Number of tasks successfully added
         */
        unsigned int wait_appendBulk(T *tasks, unsigned int count)
        {
            return taskQueue.wait_pushBulk(tasks, count);
        }

        /**
         * @brief Wait and append multiple tasks in bulk with timeout
         * @tparam Rep Time unit type for duration
         * @tparam Period Time interval type for duration
         * @param tasks Pointer to array of tasks
         * @param count Number of tasks in the array
         * @param timeout Maximum wait duration
         * @return Number of tasks successfully added before timeout
         */
        template <class Rep, class Period>
        unsigned int wait_appendBulk(T *tasks, unsigned int count,
                                     const std::chrono::duration<Rep, Period> &timeout)
        {
            return taskQueue.wait_pushBulk(tasks, count, timeout);
        }

        /**
         * @brief Worker thread processing function
         * @note Handles both single task and bulk processing modes based on batchSize
         */
        void worker()
        {
            if (batchSize == 1)
            {
                std::aligned_storage_t<sizeof(T), alignof(T)> taskBuffer;
                T *taskPtr = (T *)(&taskBuffer);

                count++;

                while (true)
                {
                    if (taskQueue.wait_pop(*taskPtr))
                    {
                        taskPtr->execute();
                        conditional_destroy(*taskPtr);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            else
            {
                T *tasks = (T *)(operator new[](batchSize * sizeof(T), std::nothrow));

                if (!tasks)
                    error.fetch_and(1);

                count++;

                while (true)
                {
                    count = taskQueue.wait_popBulk(tasks, batchSize);

                    if (count == 0)
                        break;

                    for (unsigned int i = 0; i < count; ++i)
                    {
                        tasks[i].execute();
                        conditional_destroy(tasks[i]);
                    }
                }
                operator delete[](tasks);
            }
        }

        /**
         * @brief Stop all worker threads and clean up resources
         */
        void exit()
        {
            taskQueue.stopWait();
            for (auto &th : workers)
            {
                if (th.joinable())
                    th.join();
            }
            taskQueue.release();
        }

        ~ThreadPool()
        {
            exit();
        }

        ThreadPool(const ThreadPool &) = delete;            ///< Disable copy constructor
        ThreadPool &operator=(const ThreadPool &) = delete; ///< Disable assignment operator
    };
}
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值