C++ 避免在不同线程中执行未来时破坏对象
想象一下以下情况:C++ 避免在不同线程中执行未来时破坏对象,c++,c++11,future,C++,C++11,Future,想象一下以下情况: class A { public: folly::Future<folly::Unit> fooA(std::function<void()> callback); }; class B { public: void fooB() { a_->fooA([] { doSomethingCheap_(); }) /* Executed in thread 1 */ .via(exec_.get())
class A {
public:
folly::Future<folly::Unit> fooA(std::function<void()> callback);
};
class B {
public:
void fooB() {
a_->fooA([] { doSomethingCheap_(); }) /* Executed in thread 1 */
.via(exec_.get())
.then([] { doSomethingExpensive_(); }) /* Executed in thread 2 */
}
private:
std::shared_ptr<folly::Executor> exec_;
std::shared_ptr<A> a_;
void doSomethingCheap_();
void doSomethingExpensive_();
};
A类{
公众:
folly::Future fooA(std::函数回调);
};
B类{
公众:
void fooB(){
在线程1中执行的一个->fooA([]{doSomethingCheap()})/**/
.via(exec_.get())
。然后在线程2中执行([]{dosomethingeexpensive_u()})/*操作*/
}
私人:
std::共享\u ptr exec;
std::共享的ptr a;
void doSomethingCheap_();
void dosothingexpensive_u2;;
};
如果在我们结束执行时,doSomethingCheap_uz()
objectbb
将被销毁,那么我们将得到segfault
。也许我们可以在A类
中保持弱ptr
,但当我们不仅要在B类
中使用A类
而且要在某些C类
中使用时,这种方法是不可扩展的
避免这种情况的最佳方法是什么?我不熟悉愚蠢或您正在使用的同步机制,但似乎您可以使用一个互斥保护的布尔,捕获并传递给lambda调用dosomethingeexpensive-这将是一个“穷人的加入”。锁定互斥锁,然后将布尔值翻转为true。或者,您可以使用类似于absl::Notification的东西[因为我知道这一点]
#include "absl/synchronization/notification.h"
class A {
public:
folly::Future<folly::Unit> fooA(std::function<void()> callback);
};
class B {
public:
void fooB() {
a_->fooA([] { doSomethingCheap_(); }) /* Executed in thread 1 */
.via(exec_.get())
.then([this] {
doSomethingExpensive_();
finished_.Notify();
}) /* Executed in thread 2 */
finished_.WaitForNotification();
}
private:
std::shared_ptr<folly::Executor> exec_;
std::shared_ptr<A> a_;
absl::Notification finished_;
void doSomethingCheap_();
void doSomethingExpensive_();
};
#包括“absl/synchronization/notification.h”
甲级{
公众:
folly::Future fooA(std::函数回调);
};
B类{
公众:
void fooB(){
在线程1中执行的一个->fooA([]{doSomethingCheap()})/**/
.via(exec_.get())
.然后([这个]{
doSomethingExpensive_uz();
已完成。通知();
})/*在线程2中执行*/
已完成。WaitForNotification();
}
私人:
std::共享\u ptr exec;
std::共享的ptr a;
absl::通知已完成;
void doSomethingCheap_();
void dosothingexpensive_u2;;
};
最终,加入线程似乎是正确的选择,我只是不确定folly中暴露了什么。我不熟悉folly或您正在使用的同步机制,但似乎您可以使用一个互斥保护的bool,捕获并传递给lambda调用doSomethingExpensive-这将是一个“可怜的人的加入”。锁定互斥锁,然后将bool翻转为true。或者,您可以使用类似于absl::Notification的东西[因为我知道这一点]
#include "absl/synchronization/notification.h"
class A {
public:
folly::Future<folly::Unit> fooA(std::function<void()> callback);
};
class B {
public:
void fooB() {
a_->fooA([] { doSomethingCheap_(); }) /* Executed in thread 1 */
.via(exec_.get())
.then([this] {
doSomethingExpensive_();
finished_.Notify();
}) /* Executed in thread 2 */
finished_.WaitForNotification();
}
private:
std::shared_ptr<folly::Executor> exec_;
std::shared_ptr<A> a_;
absl::Notification finished_;
void doSomethingCheap_();
void doSomethingExpensive_();
};
#包括“absl/synchronization/notification.h”
甲级{
公众:
folly::Future fooA(std::函数回调);
};
B类{
公众:
void fooB(){
在线程1中执行的一个->fooA([]{doSomethingCheap()})/**/
.via(exec_.get())
.然后([这个]{
doSomethingExpensive_uz();
已完成。通知();
})/*在线程2中执行*/
已完成。WaitForNotification();
}
私人:
std::共享\u ptr exec;
std::共享的ptr a;
absl::通知已完成;
void doSomethingCheap_();
void dosothingexpensive_u2;;
};
最终,加入线程似乎是正确的选择,我只是不确定愚蠢中暴露了什么。表达式doSomethingCheap()
和dosomethingeexpensive()
的类型为void,无法传递给其他函数。@aschepler,如果你有这个想法,你能纠正我的代码吗?不太熟悉std::function
,但为了举例而使用它。这就是executor的makeKeepAlive
的目的吗?或者也许有一种很好的方法可以使用共享ptr来保持B的活力?不过我看不到。表达式doSomethingCheap\(
和dosomethingeexpensive\)
的类型为void,无法传递给其他函数。@aschepler,如果你有这个想法,你能纠正我的代码吗?不太熟悉std::function
,但为了举例而使用它。这就是executor的makeKeepAlive
的目的吗?或者也许有一种很好的方法可以使用共享ptr来保持B的活力?不过我看不到。