weak_ptr如何知道共享资源已过期
How does a weak_ptr know that the shared resources has expired?
考虑以下代码:
#include <memory>
#include <iostream>
using namespace std;
struct MySharedStruct
{
int i;
};
void print_value_of_i(weak_ptr<MySharedStruct> weakPtr)
{
if (shared_ptr<MySharedStruct> sp = weakPtr.lock())
{ cout << "Value of i = " << sp->i << endl; }
else
{ cout << "Resource has expired"; }
}
int main()
{
shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct() );
sharedPtr->i = 5;
weak_ptr<MySharedStruct> weakPtr;
weakPtr = sharedPtr;
print_value_of_i(weakPtr);
sharedPtr.reset(new MySharedStruct() ); // <<----- How does weak_ptr know it has expired after this line executes?
sharedPtr->i = 10;
print_value_of_i(weakPtr);
return 0;
}
考虑到shared_ptr
所引用的资源基本上已被另一个资源取代,weak_ptr
如何知道它已过期?weak_ptr
会跟踪什么以确保旧共享资源被销毁并被新的共享资源替换?weak_ptr
中的方法(例如lock
(的示例定义(如果相关的话(将被理解。
从纯指针创建shared_ptr
时分配的控制块包含对象的引用计数器、指向对象本身的指针以及自定义deleter对象(如果有的话(。当引用计数器达到零时,对象被释放,指针被设置为null。因此,当对象引用计数器为零时,意味着该对象已不存在。
对于x86和x86-64,它们使用原子操作,没有显式锁定(没有互斥或自旋锁(。实现的诀窍是一个特殊的无锁(繁忙自旋的代码语言(函数atomic_conditional_increment
,它只在对象引用计数器不为零的情况下递增对象引用计数器。它用于weak_ptr::lock
函数的实现,以应对多个线程试图从对象引用计数器为零的同一weak_ptr
创建shared_ptr
时的竞争。看见http://www.boost.org/doc/libs/1_52_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
控制块本身在shared_ptr
和weak_ptr
之间共享,并且有另一个自己的引用计数器,因此它一直保持活动状态,直到对它的最后一个引用被释放。
当一个shared_ptr
被重新分配时,它指向另一个控制块,因此一个控制区块只指向一个相同的对象。换句话说,在控制块中不存在用另一个对象替换一个对象的情况。
简短回答
我怀疑大多数实现都是通过weakPtr
和sharedPtr
都引用的共享控制块来实现这一点的。当sharedPtr
重置时,它会减少控制块中的use_count
,weakPtr
可以用来测试指针是否有效。
答案很长
但我认为这可能因实施情况而异。以下是C++11标准所说的应该发生的事情:
shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct());
根据20.7.2.2.1,sharedPtr
是在拥有给定数据的情况下构建的。
weak_ptr<MySharedStruct> weakPtr;
weakPtr = sharedPtr;
根据20.7.2.3.1,构造weakPtr
,然后为其赋值sharedPtr
。在分配之后,weakPtr
和sharedPtr
现在共享给定数据的所有权。
sharedPtr.reset(new MySharedStruct());
根据20.7.2.2.4,reset(Y*)
等效于shared_ptr(Y*).swap(*this)
。换句话说,sharedPtr
用拥有新数据的临时shared_ptr
交换其内容。
交换后,sharedPtr
将拥有新数据,临时数据将与weakPtr
共享旧数据的所有权。
根据20.7.2.2.2,然后销毁临时:
- 由于临时拥有旧数据,并且不与另一个
shared_ptr
实例共享该所有权,因此它会删除旧数据 - 与临时
shared_ptr
共享所有权的所有实例都将报告比其先前值少一个的use_count()
这意味着CCD_ 33。
if (shared_ptr<MySharedStruct> sp = weakPtr.lock()) {
cout << "Value of i = " << sp->i << endl;
} else {
cout << "Resource has expired";
}
根据20.7.2.3.5,调用lock
相当于
expired() ? shared_ptr<T>() : shared_ptr<T>(*this)
CCD_ 35相当于
use_count() == 0
这意味着CCD_ 36将返回一个空的CCD_。
- 拥有或在对象之间共享资源
- 在新作用域中使用unique_lock是否等效于在使用共享资源的工作结束时解锁调用
- 是否有一种设计模式或面向对象的基本原则来处理这种共享资源的情况?
- 多线程和共享资源:使用C++定期将数据从缓冲区(数据结构)复制到文件
- 为什么我的程序寻找共享资源.dll而不是Commons.lib
- 多个线程访问共享资源
- C++11 中 3 个线程和 2 个共享资源的同步问题
- 锁定构造函数和析构函数中的共享资源
- qtmake-两个项目/目标之间的共享资源
- 在多线程程序中共享资源 C++ 与 Java
- C++/提升共享资源类,用于管理资源生命周期,如shared_ptr
- 高效读取共享资源
- 从DirectX11到Directx9共享资源
- 使用 std::weak_ptr 共享资源所有权
- 如何将共享资源对象的生存期绑定到其用户生存期的联合中?
- 线程共享资源C++
- CppUtest在测试之间共享资源,未定义引用
- 共享资源,如带宽同步
- 写入互斥的共享资源
- weak_ptr如何知道共享资源已过期