- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下线程池实现:
template<typename... event_args>
class thread_pool{
public:
using handler_type = std::function<void(event_args...)>;
thread_pool(handler_type&& handler, std::size_t N = 4, bool finish_before_exit = true) : _handler(std::forward<handler_type&&>(handler)),_workers(N),_running(true),_finish_work_before_exit(finish_before_exit)
{
for(auto&& worker: _workers)
{
//worker function
worker = std::thread([this]()
{
while (_running)
{
//wait for work
std::unique_lock<std::mutex> _lk{_wait_mutex};
_cv.wait(_lk, [this]{
return !_events.empty() || !_running;
});
//_lk unlocked
//check to see why we woke up
if (!_events.empty()) {//was it new work
std::unique_lock<std::mutex> _readlk(_queue_mutex);
auto data = _events.front();
_events.pop();
_readlk.unlock();
invoke(std::move(_handler), std::move(data));
_cv.notify_all();
}else if(!_running){//was it a signal to exit
break;
}
//or was it spurious and we should just ignore it
}
});
//end worker function
}
}
~thread_pool()
{
if(_finish_work_before_exit)
{//block destruction until all work is done
std::condition_variable _work_remains;
std::mutex _wr;
std::unique_lock<std::mutex> lk{_wr};
_work_remains.wait(lk,[this](){
return _events.empty();
});
}
_running=false;
//let all workers know to exit
_cv.notify_all();
//attempt to join all workers
for(auto&& _worker: _workers)
{
if(_worker.joinable())
{
_worker.join();
}
}
}
handler_type& handler()
{
return _handler;
}
void propagate(event_args&&... args)
{
//lock before push
std::unique_lock<std::mutex> _lk(_queue_mutex);
{
_events.emplace(std::make_tuple(args...));
}
_lk.unlock();//explicit unlock
_cv.notify_one();//let worker know that data is available
}
private:
bool _finish_work_before_exit;
handler_type _handler;
std::queue<std::tuple<event_args...>> _events;
std::vector<std::thread> _workers;
std::atomic_bool _running;
std::condition_variable _cv;
std::mutex _wait_mutex;
std::mutex _queue_mutex;
//helpers used to unpack tuple into function call
template<typename Func, typename Tuple, std::size_t... I>
auto invoke_(Func&& func, Tuple&& t, std::index_sequence<I...>)
{
return func(std::get<I>(std::forward<Tuple&&>(t))...);
}
template<typename Func, typename Tuple, typename Indicies = std::make_index_sequence<std::tuple_size<Tuple>::value>>
auto invoke(Func&& func, Tuple&& t)
{
return invoke_(std::forward<Func&&>(func), std::forward<Tuple&&>(t), Indicies());
}
};
我最近将此部分添加到析构函数中:
if(_finish_work_before_exit)
{//block destruction until all work is done
std::condition_variable _work_remains;
std::mutex _wr;
std::unique_lock<std::mutex> lk{_wr};
_work_remains.wait(lk,[this](){
return _events.empty();
});
}
目的是让析构函数阻塞,直到工作队列被完全消耗掉。
但是好像让程序陷入了僵局。 a所有的工作都完成了,但等待似乎并没有在工作完成时结束。
考虑这个例子:
std::mutex writemtx;
thread_pool<int> pool{
[&](int i){
std::unique_lock<std::mutex> lk{writemtx};
std::cout<<i<<" : "<<std::this_thread::get_id()<<std::endl;
},
8//threads
};
for (int i=0; i<8192; ++i) {
pool.propagate(std::move(i));
}
如何让析构函数等待工作完成而不造成死锁?
最佳答案
您的代码死锁的原因是 _work_remains
是一个条件变量,您的代码的任何部分都不会“通知”它。您需要将其设为类属性,并让从 _events
中获取最后一个事件的任何线程通知它。
关于c++ - 线程池 : Block destruction until all work is done,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40299150/
下面的代码说明了 destruct() 被调用了两次。我想知道为什么? class A { function hi(){ echo 'hi'; } function __destruc
我有一组存储在 PHP 数组中的客户端类对象。有时我需要 unset() 数组中的其中一个对象,但我不想担心显式关闭套接字连接。我希望 __destruct() 为我做这件事。 class A{
在 coq 中, destruct 策略有一个变体,它接受“连接析取引入模式”,允许用户为引入的变量分配名称,即使在解包复杂的归纳类型时也是如此。 coq 中的 Ltac 语言允许用户编写自定义策略。
很抱歉,如果这个问题的标题没有解释实际的问题。我找不到合适的词来命名这个问题的标题。 我有一个像这样的数据库类: class Database { private $link; private
在很多情况下,我的类都像事件对象(有一个线程)。为了避免访问冲突,我总是必须在析构函数中等待加入。这通常不是问题。 然而,想象一下发布版本有一些错误(死锁、活锁等)导致 join() 不能按时返回或根
我想知道是否有办法让 Python 避开 __init__ 中的其他函数并直接进入 __del__。例如 class API: Array = {"status" : False, "resu
这个问题在这里已经有了答案: calling destructor explicitly (2 个答案) 关闭 8 年前。 在下面的代码中,a 的析构函数被调用了两次,第一次调用似乎被忽略了: st
众所周知,电子邮件非常不安全。即使在客户端和发送电子邮件的服务器之间建立了 SSL 安全连接,当消息在 Internet 上的节点间跳跃时,它本身仍将是明文形式,使其容易受到窃听。 另一个考虑因素是发
我有两个全局变量: static mutex m; static object o; 和破坏|o|需要使用|n| ~object() { auto_lock(&m); } 但是,我发现有时候 |m
我的情况与这个老问题完全相同: WARN: Could not register destruction callback 简而言之:我看到一条警告,指出无法为某些 bean 注册销毁回调。 我的问题
我一直在审查 C++ 指针和引用,并想验证我是否理解以下来自 Wikipedia 的示例中“破坏性程序变体”的含义。 : Here's how a typical binary search tree
我想要从内部卸载应用程序的能力。示例:弹出 UIAlertView 并提示“此应用程序已过期”。用户点击“确定”,然后应用程序继续关闭并将其自身从设备中删除。有什么办法吗? 最佳答案 我认为没有办法从
我今天做了一个 git pull 并得到了以下信息: $ git pull remote: Counting objects: 8, done. remote: Compressing objects
15:11:14,676 WARN FacesRequestAttributes:121 - Could not register destruction callback [org.springfr
是否有任何关于从可以放入结构化绑定(bind)语句的方法返回的对象的销毁顺序的定义? cppreference 似乎没有提到销毁顺序,对 Godbolt 的快速测试揭示了一些与我预期不同的东西。 #i
destruct 可用于在 Coq 中拆分 and、or。不过好像也可以用来暗示?例如,我想证明 ~~(~~P -> P) Lemma test P : ~~(~~P -> P). Proof. un
我正在尝试计算出需要使用的代码行,以确定是否已在 UIActionSheet 中按下“破坏性”按钮。 我环顾四周并找到了委托(delegate)方法... - (void)actionSheet:(
出于这个问题的目的,假设我有: Parameter eq_bool : forall (A:Type), A -> A -> bool. Arguments eq_bool {A} _ _. Axio
这个问题已经有答案了: Why did ECMASCRIPT 6 reverse the sides for assignment when destructuring? [closed] (1 个回
我有以下线程池实现: template class thread_pool{ public: using handler_type = std::function; thread_po
我是一名优秀的程序员,十分优秀!