异步线程池

74 阅读1分钟
#include <iostream>
#include <future>
#include <vector>
#include <functional>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>

class ThreadPool {
public:
    ThreadPool(size_t thread_num) {
        for (size_t i = 0; i < thread_num; ++i) {
            workers_.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(queue_mutex_);
                        condition_.wait(lock, [this] { return stop_ || !task_queue_.empty(); });
                        if (stop_ && task_queue_.empty()) {
                            return;
                        }
                        task = std::move(task_queue_.front());
                        task_queue_.pop();
                    }
                    task();
                }
            });
        }
    }

    template <class F, class... Args>
    auto AddFuture(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));

        std::future<return_type> result = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            if (stop_) {
                throw std::runtime_error("enqueue on stopped ThreadPool");
            }
            task_queue_.emplace([task]() { (*task)(); });
        }
        condition_.notify_one();
        return result;
    }

    
template <class ItemType, tepename Function>
bool Visit(const int thread_num, const std::vector<ItemType>& container, Function&& visit_func, int timeout_ms = 0) {
    if (thread_num == 0) {
        return false;
    }
    int container_size = container.size();
    int item_num_for_one_thread = std::ceil((double)container_size / thread_num);

    std::vector<std::future<bool>> futures;
    futures.resize(std::min(thread_num,container_size));
    auto func_ptr = std::make_shared<Function>(std::move(visit_func));
    for (int i = 0; i < futures.size(); ++i) {
        const int start_index = i * item_num_for_one_thread;
        if (start_index >= container_size) {
            continue;
        }
        const int end_index = std::min((container_size - 1), start_index + item_num_for_one_thread - 1);
        futures[i] = AddFuture([start_index, end_index, &container, func_ptr, this]() {
            for (int j = start_index; j <= end_index; ++j) {
                bool res = (*func_ptr)(container[j]);
            }
            return true;
        });
    }
    
    if (timeout_ms == 0) {
        for (int i = 0; i < futures.size(); ++i) {
            futures[i].wait();
        }
    }
    else {
        for (int i = 0; i < futures.size(); ++i) {
            auto status = futures[i].wait_for(std::chrono::milliseconds(timeout_ms));
            if (status == std::future_status::timeout) {
                LOG_ERROR("wait for future timeout");
            }
        }
    }
    
    return true;
}

    template <class ContainerType, tepename

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            stop_ = true;
        }
        condition_.notify_all();
        for (std::thread& worker : workers_) {
            worker.join();
        }
    }

private:
    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> task_queue_;
    std::mutex queue_mutex_;
    std::condition_variable condition_;
    bool stop_ = false;
};

int main() {
    const size_t thread_num = 4; // 限定线程数量为4
    ThreadPool pool("pool", thread_num);
    std::string s = "hello world";
    auto sp = std::make_shared<std::string>("hello world");
    pool.AddFuture([sp]() {
        std::cout << *sp << std::endl;
        return true;
    });

    // visit
    // 并行将string从s_vec写到map里
    std::vector<std::string> s_vec;
    const int vec_size = 5000;
    for (int i = 0; i < vec_size; ++i) {
        s_vec.push_back(std::to_string(i));
    }

    std::mutex mu_;
    std::map<int, std::string> map_;
    auto func = [&mu_](const std::string& s) {
        std::lock_guard<std::mutex> lock(mu_);
        map_.emplace(stoi(s), s);
        return true;
    }
   bool res = pool.Visit(10, s_vec, std::move(func));
   for (const auto& [k, v]: map_) {
       std::cout <<k << ":" << v << std::endl;
   }

    return 0;
}