比如说,如果我有一个C函数(或API),它在不同的线程中调用回调,并接受const void*
形式的老式C参数。将std::shared_ptr
的副本传递到回调函数中的最有效方法是什么?
到目前为止,我一直在使用以下方法:
(我将使用一个线程来模拟我所要求的内容。)
struct My1
{
My1()
{
std::cout << "My1 constructor" << std::endl;
}
~My1()
{
std::cout << "My1 destructor" << std::endl;
}
};
void* thread1(void* pParam)
{
std::shared_ptr<My1>* pp1 = (std::shared_ptr<My1>*)pParam;
std::cout << "thread1 ref count: " << pp1->use_count() << std::endl;
delete pp1;
return 0;
}
int main(int argc, const char * argv[])
{
if(1)
{
std::shared_ptr<My1> p1 = std::make_shared<My1>();
std::cout << "ref count: " << p1.use_count() << std::endl;
std::shared_ptr<My1>* pp1 = new std::shared_ptr<My1>(p1);
pthread_t thr1;
if(pthread_create(&thr1, nullptr, thread1, (void*)pp1) != 0)
{
//Failed to start thread
delete pp1;
}
std::cout << "ref count: " << p1.use_count() << std::endl;
}
int i;
std::cin >> i;
return 0;
}
3条答案
按热度按时间62lalag41#
我假设回调线程的生命周期可能超过调用API时使用的原始
shared_ptr
的生命周期。如果不是这种情况,并且原始shared_ptr
保证比回调线程更长,则可以省去智能指针,只需传入一个原始指针,而不必担心。我想情况并非如此。这是不美观的代码,但我认为这是一个合理的(只?)选项,用于您所描述的调用您提供的回调的API的情况。
8ehkhllq2#
不动态分配共享指针;在此自动存储持续时间;否则使用智能指针的全部意义基本上就丧失了。
此外,由于您在主线程上执行
delete pp1;
,因此无法保证当您在后台线程中访问共享指针对象时,它仍然是活动的。这里需要的是一种方法来传达这样一个事实,即后台线程已经获得了对象的所有权,并且这样做的方式是在上下文对象和获得共享指针所有权的后台线程之间建立一种happens before关系。
std::latch
恰好是可以实现这个的东西。您可以通过使用mutable
(.注意:pthread不接收context作为const的指针)。**注意:**为了简单起见,我在这里使用
std::thread
,但由于它与函数指针和void指针一起使用,您应该可以轻松地调整逻辑以用于pthread或其他C多线程逻辑。gijlo24d3#
因为您需要一个副本,所以只需使用复制构造函数在
thread1
中创建一个示例。另外,不要使用new
创建shared_ptr
。这说不通啊示例:
输出: