线程一些常用功能总结
c++11通常单例模式如下:
template <typename T> class Singleton { protected: Singleton() = default; Singleton(const Singleton<T>&) = delete; Singleton& operator=(const Singleton<T>& st) = delete; static std::shared_ptr<T> _instance; public: static std::shared_ptr<T> GetInstance() { static std::once_flag s_flag; std::call_once(s_flag, [&]() { _instance = std::shared_ptr<T>(new T); }); return _instance; } void PrintAddress() { std::cout << _instance.get() << std::endl; } ~Singleton() { std::cout << "this is singleton destruct" << std::endl; } }; template <typename T> std::shared_ptr<T> Singleton<T>::_instance = nullptr; //想使用单例类,可以继承上面的模板,我们在网络编程中逻辑单例类用的就是这种方式 class LogicSystem :public Singleton<LogicSystem> { friend class Singleton<LogicSystem>; public: ~LogicSystem(){} private: LogicSystem(){} };
线程安全栈
#include <queue> #include <memory> #include <mutex> #include <condition_variable> template<typename T> class threadsafe_queue { private: mutable std::mutex mut; std::queue<T> data_queue; std::condition_variable data_cond; public: threadsafe_queue() {} threadsafe_queue(threadsafe_queue const& other) { std::lock_guard<std::mutex> lk(other.mut); data_queue = other.data_queue; } void push(T new_value) { std::lock_guard<std::mutex> lk(mut); data_queue.push(new_value); data_cond.notify_one(); } void wait_and_pop(T& value) { std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, [this] {return !data_queue.empty(); }); value = data_queue.front(); data_queue.pop(); } std::shared_ptr<T> wait_and_pop() { std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, [this] {return !data_queue.empty(); }); std::shared_ptr<T> res(std::make_shared<T>(data_queue.front())); data_queue.pop(); return res; } bool try_pop(T& value) { std::lock_guard<std::mutex> lk(mut); if (data_queue.empty()) return false; value = data_queue.front(); data_queue.pop(); return true; } std::shared_ptr<T> try_pop() { std::lock_guard<std::mutex> lk(mut); if (data_queue.empty()) return std::shared_ptr<T>(); std::shared_ptr<T> res(std::make_shared<T>(data_queue.front())); data_queue.pop(); return res; } bool empty() const { std::lock_guard<std::mutex> lk(mut); return data_queue.empty(); } };
简单线程池实现
#ifndef __THREAD_POOL_H__ #define __THREAD_POOL_H__ #include <atomic> #include <condition_variable> #include <future> #include <iostream> #include <mutex> #include <queue> #include <thread> #include <vector> class ThreadPool { public: ThreadPool(const ThreadPool&) = delete; ThreadPool& operator=(const ThreadPool&) = delete; static ThreadPool& instance() { static ThreadPool ins; return ins; } using Task = std::packaged_task<void()>; ThreadPool(unsigned int num = 5) : stop_(false) { { if (num < 1) thread_num_ = 1; else thread_num_ = num; } start(); } ~ThreadPool() { stop(); } template <class F, class... Args> auto commit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> { using RetType = decltype(f(args...)); if (stop_.load()) return std::future<RetType>{}; auto task = std::make_shared<std::packaged_task<RetType()>>( std::bind(std::forward<F>(f), std::forward<Args>(args)...)); std::future<RetType> ret = task->get_future(); { std::lock_guard<std::mutex> cv_mt(cv_mt_); tasks_.emplace([task] { (*task)(); }); } cv_lock_.notify_one(); return ret; } int idleThreadCount() { return thread_num_; } private: void start() { for (int i = 0; i < thread_num_; ++i) { pool_.emplace_back([this]() { while (!this->stop_.load()) { Task task; { std::unique_lock<std::mutex> cv_mt(cv_mt_); this->cv_lock_.wait(cv_mt, [this] { return this->stop_.load() || !this->tasks_.empty(); }); if (this->tasks_.empty()) return; task = std::move(this->tasks_.front()); this->tasks_.pop(); } this->thread_num_--; task(); this->thread_num_++; } }); } } void stop() { stop_.store(true); cv_lock_.notify_all(); for (auto& td : pool_) { if (td.joinable()) { std::cout << "join thread " << td.get_id() << std::endl; td.join(); } } } private: std::mutex cv_mt_; std::condition_variable cv_lock_; std::atomic_bool stop_; std::atomic_int thread_num_; std::queue<Task> tasks_; std::vector<std::thread> pool_; }; #endif // !__THREAD_POOL_H__
测试相关的代码
int main() { auto &m1 = ThreadPool::instance(); auto &j = ThreadPool::instance(); std::cout << "m is " << &m1 << std::endl; std::cout << "j is " << &j << std::endl; int m = 0; ThreadPool::instance().commit([](int& m) { m = 1024; std::cout << "inner set m is " << m << std::endl; }, m); std::this_thread::sleep_for(std::chrono::seconds(3)); std::cout << "m is " << m << std::endl; std::this_thread::sleep_for(std::chrono::seconds(3)); ThreadPool::instance().commit([](int& m) { m = 1024; std::cout << "inner set m is " << m << std::endl; }, std::ref(m)); std::this_thread::sleep_for(std::chrono::seconds(3)); std::cout << "m is " << m << std::endl; return 1; }