#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;
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;
});
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;
}