modern cppcpp2bgccmsvcclang

完整代码

class ThreadPool {
    std::atomic<bool> shutdown_;
    BlockingQueue<std::function<void()> > queue_;
    std::vector<std::thread> threads_;
    std::mutex mutex_;
    std::condition_variable cv_;

    // 待线程池执行的任务仿函数封装类
    class Worker {
        ThreadPool *pool_;

    public:
        Worker() = delete;

        explicit Worker(ThreadPool *pool) : pool_(pool) {}

        void operator()() const{
            while (!pool_->shutdown_) {
                std::unique_lock lock(pool_->mutex_);
                pool_->cv_.wait(lock, [this] {
                    return !pool_->queue_.empty();
                });
                auto func = pool_->queue_.pop();
                lock.unlock();
                func();
            }
        }
    };

public:
    // 默认线程数为 CPU 核数的两倍
    ThreadPool() : ThreadPool(std::thread::hardware_concurrency() * 2) {}

    explicit ThreadPool(size_t nThreads) : shutdown_(false), threads_(nThreads > 0 ? nThreads : 8) {
        for (auto &thread: threads_) {
            thread = std::thread(Worker(this));
        }
    }

    // 删除拷贝构造和拷贝赋值函数,确保任务有且只有一份
    ThreadPool(const ThreadPool &) = delete;

    ThreadPool &operator=(const ThreadPool &) = delete;

    [[maybe_unused]]
    void shutdown() {
        shutdown_ = true;
        cv_.notify_all();

        for (auto &thread: threads_) {
            if (thread.joinable()) {
                thread.join();
            }
        }
    }

    // 提交要由线程池异步执行的函数
    // C++17之后,不建议使用decltype(f(args...))和std::result_of来推导函数返回值类型,建议使用std::invoke_result
    template<typename F, typename... Args>
    auto submit(F &&f, Args &&... args) -> std::future<std::invoke_result_t<F, Args...>> {
        // 创建一个准备执行的函数对象
        auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        // 将其封装到共享的智能指针中,以便复制和传递
        auto taskPtr = std::make_shared<std::packaged_task<std::invoke_result_t<F, Args...>()> >(func);
        // 将封装的任务包装到 std::function<void()> 中
        const std::function<void()> wrapperFunc = [taskPtr] {
            (*taskPtr)();
        };
        // 将包装后的通用函数添加到队列中
        queue_.push(wrapperFunc);
        // 唤醒一个正在等待的线程
        cv_.notify_one();
        // 返回future
        return taskPtr->get_future();
    }
};

文章作者: Liccsu
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Liccsu's blog
笔记 C++
喜欢就支持一下吧
打赏
微信 微信