最近我在想一个使用c ++ 11的高性能事件驱动的多线程框架。它主要考虑了{+ 1}},std::thread
,std::condition_variable
,std::mutex
等c ++ 11设施。一般来说,这个框架有三个基本组成部分:工作,工人和流线,好吧,它似乎是一个真正的工厂。当用户在服务器端构建他的业务模型时,他只需要考虑数据及其处理器。一旦建立了模型,用户只需要构造数据类继承的作业和处理器类继承的worker。
例如:
std::shared_ptr
当服务器获取数据时,它只是通过数据源回调线程中的class Data : public job {};
class Processsor : public worker {};
新建一个Data对象并调用streamline。 auto data = std::make_shared<Data>()
将处理器和数据传输到其他线程。当然,用户不必考虑释放内存。精简。 job_dispatch
主要做以下事情:
job_dispatch
void evd_thread_pool::job_dispatch(std::shared_ptr<evd_thread_job> job) {
auto task = std::make_shared<evd_task_wrap>(job);
task->worker = streamline.worker;
// worker has been registered in streamline first of all
{
std::unique_lock<std::mutex> lck(streamline.mutex);
streamline.task_list.push_back(std::move(task));
}
streamline.cv.notify_all();
}
中使用的evd_task_wrap
定义为:
job_dispatch
最后,task_wrap将通过struct evd_task_wrap {
std::shared_ptr<evd_thread_job> order;
std::shared_ptr<evd_thread_processor> worker;
evd_task_wrap(std::shared_ptr<evd_thread_job>& o)
:order(o) {}
};
对象task_list
分派到处理线程中。并且处理线程主要执行以下操作:
std::list
但我不知道为什么这个过程经常会在void evd_factory_impl::thread_proc() {
std::shared_ptr<evd_task_wrap> wrap = nullptr;
while (true) {
{
std::unique_lock<std::mutex> lck(streamline.mutex);
if (streamline.task_list.empty())
streamline.cv.wait(lck,
[&]()->bool{return !streamline.task_list.empty();});
wrap = std::move(streamline.task_list.front());
streamline.task_list.pop_front();
}
if (-1 == wrap->order->get_type())
break;
wrap->worker->process_task(wrap->order);
wrap.reset();
}
}
函数中崩溃。并且coredump提示有时包裹是一个空的shared_ptr或段错误发生在thread_proc
中,在wrap.reset()中调用。我认为shared_ptr在这种情况下有线程同步问题,而我知道shared_ptr中的控制块是线程安全的。当然,_Sp_counted_ptr_inplace::_M_dispose
和job_dispatch
中的shared_ptr是不同的shared_ptr对象,即使它们指向相同的存储。有没有人对如何解决这个问题有更具体的建议?或者,如果存在类似的轻量级框架,使用c ++ 11进行自动内存管理
process_task的例子如:
thread_proc
答案 0 :(得分:-1)
我在您的代码中发现了一个问题,该问题可能与否有关:
您使用条件变量中的notify_all
。这将唤醒所有线程从睡眠状态。如果你将wait
包裹在while循环中就可以了,例如:
while (streamline.task_list.empty())
streamline.cv.wait(lck, [&]()->bool{return !streamline.task_list.empty();});
但由于您使用的是if
,所有主题都会离开wait
。如果您调度单个产品并具有多个消费者线程,则除了一个线程之外的所有线程都会在任务列表为空时调用wrap = std::move(streamline.task_list.front());
并导致UB。