veriosn 2
This commit is contained in:
commit
4bc2259787
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.24)
|
||||||
|
project(thread_pool_v2)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
aux_source_directory(pool DIR_POOL)
|
||||||
|
|
||||||
|
add_executable(thread_pool_v2 main.cpp ${DIR_POOL})
|
49
main.cpp
Normal file
49
main.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
#include <csignal>
|
||||||
|
#include "pool/ThreadPool.h"
|
||||||
|
std::random_device rd; // 真实随机数产生器
|
||||||
|
|
||||||
|
std::mt19937 mt(rd()); //生成计算随机数mt
|
||||||
|
|
||||||
|
std::uniform_int_distribution<int> dist(-1000, 1000); //生成-1000到1000之间的离散均匀分布数
|
||||||
|
|
||||||
|
auto rnd = std::bind(dist, mt);
|
||||||
|
|
||||||
|
// 添加两个数字的简单函数并打印结果
|
||||||
|
|
||||||
|
void multiply(const int a, const int b)
|
||||||
|
{
|
||||||
|
const int res = a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ThreadPool* pool = new ThreadPool(10);
|
||||||
|
|
||||||
|
time_t time1 = 0;
|
||||||
|
time_t time2 = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000000; ++i) {
|
||||||
|
time_t begin = time(NULL);
|
||||||
|
pool->pushTask(multiply, rnd(), rnd());
|
||||||
|
time_t end = time(NULL);
|
||||||
|
time1 += end -begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000000; ++i) {
|
||||||
|
int a = rnd();
|
||||||
|
int b = rnd();
|
||||||
|
time_t begin = time(NULL);
|
||||||
|
std::thread t = std::thread([&]() {
|
||||||
|
const int res = a * b;
|
||||||
|
});
|
||||||
|
t.join();
|
||||||
|
time_t end = time(NULL);
|
||||||
|
time2 += end - begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << time1 << std::endl;
|
||||||
|
std::cout << time2 << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
79
pool/TaskQueue.h
Normal file
79
pool/TaskQueue.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 23-4-12.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef THREAD_POOL_V2_TASKQUEUE_H
|
||||||
|
#define THREAD_POOL_V2_TASKQUEUE_H
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include <functional>
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class TaskQueue {
|
||||||
|
public:
|
||||||
|
TaskQueue() {}
|
||||||
|
TaskQueue(TaskQueue&& taskQueue) {}
|
||||||
|
~TaskQueue() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool empty() {
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
return m_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() {
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
return m_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void press(T& t) {
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
m_queue.emplace(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eject(T& t) {
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_queue.empty()) return false;
|
||||||
|
t = event(std::move(m_queue.front()));
|
||||||
|
m_queue.pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ejects(std::queue<event>& ts, size_t size) {
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_queue.empty()) return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
ts.emplace(std::move(event(index++, m_queue.front())));
|
||||||
|
m_queue.pop();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sub_swap(TaskQueue<event>& dest, size_t size) {
|
||||||
|
std::queue<event> queue;
|
||||||
|
|
||||||
|
bool st = this->ejects(queue, size);
|
||||||
|
if (!st) {
|
||||||
|
return st;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
dest.press(queue.front());
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::queue<T> m_queue;
|
||||||
|
std::mutex m_mutex;
|
||||||
|
size_t index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //THREAD_POOL_V2_TASKQUEUE_H
|
66
pool/ThreadPool.cpp
Normal file
66
pool/ThreadPool.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 23-4-12.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ThreadPool.h"
|
||||||
|
|
||||||
|
class event;
|
||||||
|
|
||||||
|
class ThreadPool::thread_tasks {
|
||||||
|
friend ThreadPool;
|
||||||
|
public:
|
||||||
|
explicit thread_tasks(ThreadPool *pool) :
|
||||||
|
pthread_id(pthread_self()), terminate(false), is_working(false), pool(pool), events(TaskQueue<event>()) {}
|
||||||
|
|
||||||
|
void operator () () {
|
||||||
|
while (true) {
|
||||||
|
// 为线程环境变量加锁, 互访问工作线程的休眠与唤醒
|
||||||
|
std::unique_lock<std::mutex> lock(pool->m_conditional_mutex);
|
||||||
|
|
||||||
|
if (events.size() <= 10 && !pool->m_tasks.empty()) {
|
||||||
|
size_t num = pool->m_tasks.size() / pool->m_threads.size();
|
||||||
|
num = num <= 1 ? 1 : num;
|
||||||
|
|
||||||
|
bool st = pool->m_tasks.sub_swap(events, num);
|
||||||
|
if (!st) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!events.empty()) {
|
||||||
|
event fun = event(0, std::function<void()>());
|
||||||
|
bool st = events.eject(fun);
|
||||||
|
if (st)
|
||||||
|
fun();
|
||||||
|
} else {
|
||||||
|
pool->m_conditional_lock.wait(lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
pthread_t pthread_id; // 线程id
|
||||||
|
bool terminate; // 是否需要结束的标志
|
||||||
|
bool is_working; // 该事件是否在工作
|
||||||
|
ThreadPool* pool; // 所属线程池
|
||||||
|
|
||||||
|
TaskQueue<event> events;// 任务队列
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ThreadPool::ThreadPool(const int n_threads) :
|
||||||
|
m_threads(std::vector<std::thread>(n_threads)), m_shutdown(false) {
|
||||||
|
|
||||||
|
for (auto & m_thread : m_threads) {
|
||||||
|
m_thread = std::thread(thread_tasks(this)); // 分配工作线程
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
56
pool/ThreadPool.h
Normal file
56
pool/ThreadPool.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 23-4-12.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef THREAD_POOL_V2_THREADPOOL_H
|
||||||
|
#define THREAD_POOL_V2_THREADPOOL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "TaskQueue.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <functional>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
class ThreadPool {
|
||||||
|
protected:
|
||||||
|
class thread_tasks;
|
||||||
|
public:
|
||||||
|
explicit ThreadPool(int n_threads = 4);
|
||||||
|
|
||||||
|
template<class F, class... Args>
|
||||||
|
auto pushTask(F && f, Args &&... args) -> std::future<decltype(f(args...))>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TaskQueue<std::function<void()>> m_tasks;
|
||||||
|
std::vector<std::thread> m_threads;
|
||||||
|
bool m_shutdown;
|
||||||
|
std::mutex m_conditional_mutex; // 线程休眠锁互斥变量
|
||||||
|
std::condition_variable m_conditional_lock; //条件变量
|
||||||
|
|
||||||
|
static int preemption_event_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class F, class... Args>
|
||||||
|
auto ThreadPool::pushTask(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
|
||||||
|
std::function<decltype(f(args...))()> function = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
|
auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(function);
|
||||||
|
|
||||||
|
// Warp packaged task into void function
|
||||||
|
std::function<void()> warpper_func = [task_ptr]()
|
||||||
|
{
|
||||||
|
(*task_ptr)();
|
||||||
|
};
|
||||||
|
|
||||||
|
m_tasks.press(warpper_func);
|
||||||
|
|
||||||
|
// 唤醒一个等待中的线程
|
||||||
|
m_conditional_lock.notify_one();
|
||||||
|
// 返回先前注册的任务指针
|
||||||
|
return task_ptr->get_future();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //THREAD_POOL_V2_THREADPOOL_H
|
24
pool/event.h
Normal file
24
pool/event.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 23-4-12.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef THREAD_POOL_V2_EVENT_H
|
||||||
|
#define THREAD_POOL_V2_EVENT_H
|
||||||
|
|
||||||
|
struct event {
|
||||||
|
int event_id;
|
||||||
|
bool terminate; // 是否需要结束的标志
|
||||||
|
bool is_working; // 该事件是否在工作
|
||||||
|
pthread_t pthread_id; // 线程id
|
||||||
|
std::function<void()> function_;
|
||||||
|
|
||||||
|
event(int eventId, const std::function<void()>& function)
|
||||||
|
: event_id(eventId), terminate(false), is_working(false), pthread_id(pthread_self()),
|
||||||
|
function_(function) {}
|
||||||
|
|
||||||
|
void operator() () {
|
||||||
|
function_();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //THREAD_POOL_V2_EVENT_H
|
Loading…
x
Reference in New Issue
Block a user