Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is diffrence between lock() and expired()? weak_ptr C++

Tags:

Recently I started at C++11. I studied about weak_ptr. There exist two ways of getting raw pointer.

  1. lock() function

    shared_ptr<Foo> spFoo = wpPtr.lock();  if(spFoo) {     spFoo->DoSomething(); } 
  2. expired() function

    if(!wpPtr.expired()) {     shared_ptr<Foo> spFoo = wpPtr.lock();     spFoo->DoSomething(); } 

Which is the better way? What is different between the two ways?

like image 204
zeno Avatar asked Jun 07 '16 12:06

zeno


People also ask

Is Weak_ptr lock thread safe?

Using weak_ptr and shared_ptr across threads is safe; the weak_ptr/shared_ptr objects themselves aren't thread-safe.

What is weak pointer lock?

weak_ptr::lockCreates a new std::shared_ptr that shares ownership of the managed object. If there is no managed object, i.e. *this is empty, then the returned shared_ptr also is empty.

What is Weak_ptr in C++?

Defined in header <memory> template< class T > class weak_ptr; (since C++11) std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

How is Weak_ptr implemented?

To implement weak_ptr , the "counter" object stores two different counters: The "use count" is the number of shared_ptr instances pointing to the object. The "weak count" is the number of weak_ptr instances pointing to the object, plus one if the "use count" is still > 0.


1 Answers

So shared ptr and weak ptr are thread safe, in that if you have an instance of the object local to a given thread, and they share a common pointed-to object, you can interact with them in one thread and another and everything works.

For this to work properly, you have to use them properly.

wp.expired() is only useful to do things like "remove every expired weak ptr from a buffer". It is not useful for the purpose you put it.

Every weak pointer, once expired, remains expired. But an engaged weak pointer can become expired immediately after you verify it is engaged.

if(!wpPtr.expired())  {   // <<--- here   shared_ptr<Foo> spFoo = wpPtr.lock();   spFoo->DoSomething(); } 

At <<--- here we know nothing about the state of wpPtr in a multi-threaded environment. It could be expired or not expired. On the other hand:

if(wpPtr.expired())  {   // <<--- there } 

At <<--- there we do know the weak pointer is expired.

Like with file io and other kinds of "transactional" operations, the only way to check if you can do something is try to do it. Between determining you should be able to do it and doing it, the state could change and the operation could fail.

You can sometimes work out that you almost certainly could not do it early, which is sometimes useful, but you cannot be certain you can do it until you try. The attempt to try can fail, at which point you handle the error.

if(auto spFoo = wpPtr.lock())  {   spFoo->DoSomething(); } 

this is the "right" way to interact with a weak pointer. Test for the validity of the weak pointer and get the shared pointer in the same operation.

Creating a spFoo outside of the if() header is acceptable, I prefer this technique as the scope of the spFoo is limited exactly to the zone where it is valid.

The other preferred technique is early exit:

auto spFoo = wpPtr.lock();  if(!spFoo) return error("wp empty");  spFoo->DoSomething(); 

which makes the "expected" execution of the code flow in a flat line without indentation or conditions or jumps.

like image 124
Yakk - Adam Nevraumont Avatar answered Oct 14 '22 06:10

Yakk - Adam Nevraumont