I ran across enable_shared_from_this while reading the Boost.Asio examples and after reading the documentation I am still lost for how this should correctly be used. Can someone please give me an example and explanation of when using this class makes sense.
It enables you to get a valid shared_ptr instance to this, when all you have is this. Without it, you would have no way of getting a shared_ptr to this, unless you already had one as a member. This example from the boost documentation for enable_shared_from_this:
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
int main()
{
shared_ptr<Y> p(new Y);
shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
The method f() returns a valid shared_ptr, even though it had no member instance. Note that you cannot simply do this:
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_ptr<Y>(this);
}
}
The shared pointer that this returned will have a different reference count from the "proper" one, and one of them will end up losing and holding a dangling reference when the object is deleted.
enable_shared_from_this has become part of C++ 11 standard. You can also get it from there as well as from boost.
from Dr Dobbs article on weak pointers, I think this example is easier to understand (source: http://drdobbs.com/cpp/184402026):
...code like this won't work correctly:
int *ip = new int;
shared_ptr<int> sp1(ip);
shared_ptr<int> sp2(ip);
Neither of the two shared_ptr objects knows about the other, so both will try to release the resource when they are destroyed. That usually leads to problems.
Similarly, if a member function needs a shared_ptr object that owns the object that it's being called on, it can't just create an object on the fly:
struct S
{
shared_ptr<S> dangerous()
{
return shared_ptr<S>(this); // don't do this!
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->dangerous();
return 0;
}
This code has the same problem as the earlier example, although in a more subtle form. When it is constructed, the shared_ptr object sp1 owns the newly allocated resource. The code inside the member function S::dangerous doesn't know about that shared_ptr object, so the shared_ptr object that it returns is distinct from sp1. Copying the new shared_ptr object to sp2 doesn't help; when sp2 goes out of scope, it will release the resource, and when sp1 goes out of scope, it will release the resource again.
The way to avoid this problem is to use the class template enable_shared_from_this. The template takes one template type argument, which is the name of the class that defines the managed resource. That class must, in turn, be derived publicly from the template; like this:
struct S : enable_shared_from_this<S>
{
shared_ptr<S> not_dangerous()
{
return shared_from_this();
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->not_dangerous();
return 0;
}
When you do this, keep in mind that the object on which you call shared_from_this must be owned by a shared_ptr object. This won't work:
int main()
{
S *p = new S;
shared_ptr<S> sp2 = p->not_dangerous(); // don't do this
}
Here's my explanation, from a nuts and bolts perspective (top answer didn't 'click' with me). *Note that this is the result of investigating the source for shared_ptr and enable_shared_from_this that comes with Visual Studio 2012. Perhaps other compilers implement enable_shared_from_this differently...*
enable_shared_from_this<T> adds a private weak_ptr<T> instance to T which holds the 'one true reference count' for the instance of T.
So, when you first create a shared_ptr<T> onto a new T*, that T*'s internal weak_ptr gets initialized with a refcount of 1. The new shared_ptr basically backs onto this weak_ptr.
T can then, in its methods, call shared_from_this to obtain an instance of shared_ptr<T> that backs onto the same internally stored reference count. This way, you always have one place where T*'s ref-count is stored rather than having multiple shared_ptr instances that don't know about each other, and each think they are the shared_ptr that is in charge of ref-counting T and deleting it when their ref-count reaches zero.
There is one particular case where I find enable_shared_from_this extremely useful: Thread safety when using asynchronous callback.
Imagine class Client has a member of type AsynchronousPeriodicTimer:
struct AsynchronousPeriodicTimer
{
// call this periodically on some thread...
void SetCallback(std::function<void(void)> callback);
void ClearCallback(); // clears the callback
}
struct Client
{
Client(std::shared_ptr< AsynchronousPeriodicTimer> timer)
: _timer(timer)
{
_timer->SetCallback(
[this]
()
{
assert(this); // what if 'this' is already dead because ~Client() has been called?
std::cout << ++_counter << '\n';
}
);
}
~Client()
{
// clearing the callback is not in sync with the timer, and can actually occur while the callback code is running
_timer->ClearCallback();
}
int _counter = 0;
std::shared_ptr< AsynchronousPeriodicTimer> _timer;
}
int main()
{
auto timer = std::make_shared<AsynchronousPeriodicTimer>();
{
auto client = std::make_shared<Client>(timer);
// .. some code
// client dies here, there is a race between the client callback and the client destructor
}
}
The client class subscribes a callback function to the periodic timer. Once the client object goes out of scope, there is a race condition between the client's callback and the client's destructor. The callback may be invoked with a dangling pointer!
The solution: using enable_shared_from_this to extend the object lifetime for the duration of the callback invocation.
struct Client : std::enable_shared_from_this<Client>
{
Client(std::shared_ptr< AsynchronousPeriodicTimer> timer)
: _timer(timer)
{
}
void Init()
{
auto captured_self = weak_from_this(); // weak_ptr to avoid cyclic references with shared_ptr
_timer->SetCallback(
[captured_self]
()
{
if (auto self = captured_self.lock())
{
// 'this' is guaranteed to be non-nullptr. we managed to promote captured_self to a shared_ptr
std::cout << ++self->_counter << '\n';
}
}
);
}
~Client()
{
// the destructor cannot be called while the callback is running. shared_ptr guarantees this
_timer->ClearCallback();
}
int _counter = 0;
std::shared_ptr< AsynchronousPeriodicTimer> _timer;
}
The mechanism of enable_shared_from_this, combined with the inherent thread safety of std::shared_ptr reference counting, enable us to ensure that the Client object cannot be destructed while the callback code is accessing its internal members.
Note that the Init method is separated from the constructor since the initialization process of enable_shared_from_this is not finalized until the constructor exits. Hence the extra method. It is generally unsafe to subscribe an asynchronous callback from within a constructor since the callback may access uninitialized fields.
Note that using a boost::intrusive_ptr does not suffer from this problem.
This is often a more convenient way to get around this issue.
It's exactly the same in c++11 and later: It is to enable the ability to return this as a shared pointer since this gives you a raw pointer.
in other word, it allows you to turn code like this
class Node {
public:
Node* getParent const() {
if (m_parent) {
return m_parent;
} else {
return this;
}
}
private:
Node * m_parent = nullptr;
};
into this:
class Node : std::enable_shared_from_this<Node> {
public:
std::shared_ptr<Node> getParent const() {
std::shared_ptr<Node> parent = m_parent.lock();
if (parent) {
return parent;
} else {
return shared_from_this();
}
}
private:
std::weak_ptr<Node> m_parent;
};
Related
I wondered whether the following code is safe with respect to the fact that the signal might be triggered by a different thread:
using IntSignal = boost::signals2::signal<void(int)>;
class Foo
{
public:
Foo(IntSignal& signal)
: some_resource(new int(0))
{
scoped_connection = signal.connect([this](int i) { some_action(i); });
}
~Foo()
{
delete some_resource;
}
private:
void some_action(int i)
{
*some_resource = i;
}
int* some_resource;
boost::signals2::scoped_connection scoped_connection;
}
EDIT: added an imaginary resource, destructor and an implementation for some_action to make it more clear. With this question I would like to clarify whether my assumption is correct that the signal's slot might be called after Foo's destructor but before scoped_connection's destructor. I omitted a mutex protecting some_resource for brevity, however, it is not relevant for the question.
Although the connection will be dropped when a Foo instance is destroyed, there might be a tiny gap betwen Foo's own destructor invocation and the destruction of Foo's members. This might be even more problematic if resources are being used within some_action after they have been destructed.
Should I rather use normal connections and disconnect them in Foo's destructor? And would it be safe to have the scoped_connection member as last member of the class (that should get destroyed first) and omit any destruction logic?
You are right, there is a possible race if Foo's destructor is invoked while the signal is running and accessing some_resource.
A safe solution would be to extend the life of Foo while the slots are running:
class Foo : public std::enable_shared_from_this<Foo>
{
public:
Foo(IntSignal& signal)
: some_resource(new int(0))
{
// moved connection initialization to a method since weak_from_this will
// be empty inside the constructor. It is initialized only afterwards.
// It also make sense to connect your signal only after object
// is fully initialized
}
void InitConnection()
{
auto weak_self = weak_from_this();
scoped_connection = signal.connect(
[weak_self](int i)
{
if (auto self = weak_self.lock())
{
// we managed to promote weak_self to a shared_ptr, 'this' will be alive
// as long as this scope lives
some_action(i); // safe
}
});
}
~Foo()
{
// will only be invoked after Foo's reference count drops to zero.
// not during the signal is emitted
delete some_resource;
}
private:
void some_action(int i)
{
*some_resource = i;
}
int* some_resource;
boost::signals2::scoped_connection scoped_connection;
}
Notes:
enable_shared_from_this initializes a weak_ptr to 'this'. It is a great tool for the situation you described. See more here.
Make sure you create Foo as a shared_ptr, otherwise weak_from_this will not work.
Remember: Foo is shared between 2 threads.
I need to have access to an object which is implemented in a different concrete class. So I decided to use std::shared_ptr. I would like to know whether usage of std::shared_ptr is appropriate here, if not please suggest whether I should go with std::weak_ptr. So far I have been using raw pointers but now I decided to use smart pointers in my project, But I'm unable to decide which one should I use here. The following code snippet is analogous to what I'm trying to do in my project.
#include <iostream>
#include <memory>
class data
{
public:
data()
{
std::cout<<"\n data constructor Called"<<std::endl;
}
~data()
{
std::cout<<"\n data destructor Called"<<std::endl;
}
int GetData()
{
return val;
}
void SetData(int & val)
{
this->val = val;
}
private:
int val;
};
class sample
{
public:
sample();
~sample();
void GetShared(std::shared_ptr<data> & arg);
std::shared_ptr<data> sPtr;
};
sample::sample()
{
sPtr = std::make_shared<data>();
}
sample::~sample()
{
}
void sample::GetShared(std::shared_ptr<data> & arg)
{
arg = sPtr;
}
int main()
{
int val = 40;
sample obj;
{
std::shared_ptr<data> temp1;
obj.GetShared(temp1);
temp1->SetData(val);
std::cout<<"\n Data : "<<temp1->GetData()<<std::endl;
} // Just to understand whether pointer gets deleted if temp1 goes out of scope.
{
std::shared_ptr<data> temp2;
obj.GetShared(temp2);
val = 20;
temp2->SetData(val);
std::cout<<"\n Data : "<<temp2->GetData()<<std::endl;
}
return 0;
}
You would use shared_pointer to share ownership of some resource, when you don't have a clear owner of that resource.
Here it would be useful if you don't know if obj goes out of scope before temp1 and temp2 is done with the data. However, in this example it is clear that obj and the data object it holds will outlive the user. In that case you could just as well return a normal pointer, or perhaps a reference to the data.
Using a shared_pointer (or a weak_pointer) doesn't buy you anything, except added complexity.
In your code
sample obj;
{
std::shared_ptr<data> temp1;
obj.GetShared(temp1);
temp1->SetData(val);
std::cout<<"\n Data : "<<temp1->GetData()<<std::endl;
} // Just to understand whether pointer gets deleted if temp1 goes out of scope.
The data will not get deleted, because it is pointing to something that is held by obj, which is still alive.
I think the answer should depend on whether a data object can live after its corresponding sample object died:
If yes, then it should return a std::shared_ptr.
If not, then it should return a std::weak_ptr.
The difference between shared_ptr and weak_ptr is that weak_ptr does not increase the ref count on the object and does prevent the object from being deleted.
This has its pros and cons, if you perform async operations after you obtain the pointer and are unsure whether the object that provided the data has been destroyed then you can use weak_ptr and check if you still have access to the object.
If not then keep it simple and use shared_ptr.
You have two questions you need to ask yourself.
1) Will the calling object that gets the pointer from sample outlive the sample object?
If not then sample should use a std::unique_ptr and return a raw pointer or a reference.
2) If the calling object does outlive the sample object, does it mind if the data object gets destroyed before it does?
If not then return a std::weak_ptr that can be used to test if the data object is still alive before using it.
Otherwise return a std::shared_ptr to guarantee the data object lives as long as the calling object.
Summary:
If the calling object will not outlive the sample object:
class sample
{
std::unique_ptr<data> ptr; // UNIQUE (not shared)
public:
data* GetData() { return ptr.get(); }
};
If the calling object may outlive the sample object but doesn't care if the data object lives as long as it does:
class sample
{
std::shared_ptr<data> ptr;
public:
std::weak_ptr<data> GetData() { return ptr; }
};
If the calling object may outlive the sample object and needs to data object to keep living too:
class sample
{
std::shared_ptr<data> ptr;
public:
std::shared_ptr<data> GetData() { return ptr; }
};
I m writing a library.
WITHOUT using smart pointer. Is it this class safe enough to emulate retain/release behaviour?
Or is there any library already doing things like this?
class FooBase {
private:
std::atomic<uint32_t> m_retainCount;
public:
FooBase()
{
m_retainCount = 1;
};
virtual ~FooBase()
{
assert(m_retainCount == 0); // Prevent from direct delete without release()
//clean-up if any
};
void *release()
{
m_retainCount--;
if (!m_retainCount)
delete this;
return this;
};
void *retain()
{
m_retainCount++;
return this;
};
};
Imagine if your thread gets swapped right after the branch in release and before the call to delete.
Another thread could come and request a retain, therefore obtaining a pointer to a soon to be deleted object.
To answer the second part, std::shared_ptr is thread-safe. It has the additional benefit of being able to use non-portable tricks internally because it's formally part of the compiler.
I love Boost's smart_ptr features and the ability to convert to and from a shared_ptr and weak_ptr, but since the reference count is not contained in the pointed class itself, the following code does not work (and it shouldn't).
A *a = new A;
shared_ptr<A> aPtr1(a);
{
shared_ptr<A> aPtr2(a);
// The reference counts of aPtr1 and aPtr2 are both 1.
} // At this point, `a` is destructed by aPtr2.
aPtr1->foo(); // And... SIGTERM
I believe the JUCE framework has this functionality. [ReferenceCountedObject and ReferenceCountedObjectPtr]
However, I'd rather use Boost for my application. Is it possible to allow Boost smart_ptrs to look for the reference count in the pointed class rather than the private boost::detail::shared_count instance?
Simple solution:
A *a = new A;
shared_ptr<A> aPtr1(a);
{
// construct new shared pointer from old one.
shared_ptr<A> aPtr2(aPtr1);
}
aPtr1->foo();
If you want something more complicated, see http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html :
The header <boost/enable_shared_from_this.hpp> defines the class template enable_shared_from_this. It is used as a base class that allows a shared_ptr to the current object to be obtained from within a member function.
Edit: I should have mentioned that enable_shared_from_this has some unfortunate issues with derivation. However, the following works with c++11; I didn't try it with boost but I suppose it should work there, too. I think it's a bit of a hack; using raw pointers when you use shared_ptr's is bound to end in tears:
struct X : std::enable_shared_from_this {
/* stuff */
};
struct Y : X {
/* stuff */
void yonly() {};
};
int main() {
Y* y = new Y;
shared_ptr<Y> sy(y);
sy->yonly();
{
auto sy2 = std::shared_ptr<Y>(y->shared_from_this(), y);
sy2->yonly();
}
std::cout << "Block ended" << std::endl;
return 0;
}
boost::intrusive_ptr likely fits your requirements.
To note however, with shared_ptr, you should construct them as follows:
shared_ptr<A> aPtr1 = boost::make_shared<A>();
This is not exception safe:
// call this as in shared_ptr<T> foo = create_intrusive_shared( new T(blah) );
// This takes ownership of the pointer you pass it.
template<typename T>
std::shared_ptr<T> create_intrusive_shared( T* t )
{
auto retval = std::shared_ptr<T>( t, []( T* cleanup )
{
if (cleanup)
cleanup->RemoveRef();
});
return retval;
}
// Call this if you have an existing instance of T, whose ownership is being
// maintained elsewhere. Do not call it with new T() as an argument, unless
// new instances of T are created with a 0 ref count
template<typename T>
std::shared_ptr<T> make_intrusive_shared( T* t )
{
if (t)
t->AddRef();
auto retval = create_intrusive_shared(t);
return retval;
}
Making them exception safe takes a bit more work. You will want to reimplement make_shared, but tag the resulting shared_ptr with a cleanup function.
I ran across enable_shared_from_this while reading the Boost.Asio examples and after reading the documentation I am still lost for how this should correctly be used. Can someone please give me an example and explanation of when using this class makes sense.
It enables you to get a valid shared_ptr instance to this, when all you have is this. Without it, you would have no way of getting a shared_ptr to this, unless you already had one as a member. This example from the boost documentation for enable_shared_from_this:
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
int main()
{
shared_ptr<Y> p(new Y);
shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
The method f() returns a valid shared_ptr, even though it had no member instance. Note that you cannot simply do this:
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_ptr<Y>(this);
}
}
The shared pointer that this returned will have a different reference count from the "proper" one, and one of them will end up losing and holding a dangling reference when the object is deleted.
enable_shared_from_this has become part of C++ 11 standard. You can also get it from there as well as from boost.
from Dr Dobbs article on weak pointers, I think this example is easier to understand (source: http://drdobbs.com/cpp/184402026):
...code like this won't work correctly:
int *ip = new int;
shared_ptr<int> sp1(ip);
shared_ptr<int> sp2(ip);
Neither of the two shared_ptr objects knows about the other, so both will try to release the resource when they are destroyed. That usually leads to problems.
Similarly, if a member function needs a shared_ptr object that owns the object that it's being called on, it can't just create an object on the fly:
struct S
{
shared_ptr<S> dangerous()
{
return shared_ptr<S>(this); // don't do this!
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->dangerous();
return 0;
}
This code has the same problem as the earlier example, although in a more subtle form. When it is constructed, the shared_ptr object sp1 owns the newly allocated resource. The code inside the member function S::dangerous doesn't know about that shared_ptr object, so the shared_ptr object that it returns is distinct from sp1. Copying the new shared_ptr object to sp2 doesn't help; when sp2 goes out of scope, it will release the resource, and when sp1 goes out of scope, it will release the resource again.
The way to avoid this problem is to use the class template enable_shared_from_this. The template takes one template type argument, which is the name of the class that defines the managed resource. That class must, in turn, be derived publicly from the template; like this:
struct S : enable_shared_from_this<S>
{
shared_ptr<S> not_dangerous()
{
return shared_from_this();
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->not_dangerous();
return 0;
}
When you do this, keep in mind that the object on which you call shared_from_this must be owned by a shared_ptr object. This won't work:
int main()
{
S *p = new S;
shared_ptr<S> sp2 = p->not_dangerous(); // don't do this
}
Here's my explanation, from a nuts and bolts perspective (top answer didn't 'click' with me). *Note that this is the result of investigating the source for shared_ptr and enable_shared_from_this that comes with Visual Studio 2012. Perhaps other compilers implement enable_shared_from_this differently...*
enable_shared_from_this<T> adds a private weak_ptr<T> instance to T which holds the 'one true reference count' for the instance of T.
So, when you first create a shared_ptr<T> onto a new T*, that T*'s internal weak_ptr gets initialized with a refcount of 1. The new shared_ptr basically backs onto this weak_ptr.
T can then, in its methods, call shared_from_this to obtain an instance of shared_ptr<T> that backs onto the same internally stored reference count. This way, you always have one place where T*'s ref-count is stored rather than having multiple shared_ptr instances that don't know about each other, and each think they are the shared_ptr that is in charge of ref-counting T and deleting it when their ref-count reaches zero.
There is one particular case where I find enable_shared_from_this extremely useful: Thread safety when using asynchronous callback.
Imagine class Client has a member of type AsynchronousPeriodicTimer:
struct AsynchronousPeriodicTimer
{
// call this periodically on some thread...
void SetCallback(std::function<void(void)> callback);
void ClearCallback(); // clears the callback
}
struct Client
{
Client(std::shared_ptr< AsynchronousPeriodicTimer> timer)
: _timer(timer)
{
_timer->SetCallback(
[this]
()
{
assert(this); // what if 'this' is already dead because ~Client() has been called?
std::cout << ++_counter << '\n';
}
);
}
~Client()
{
// clearing the callback is not in sync with the timer, and can actually occur while the callback code is running
_timer->ClearCallback();
}
int _counter = 0;
std::shared_ptr< AsynchronousPeriodicTimer> _timer;
}
int main()
{
auto timer = std::make_shared<AsynchronousPeriodicTimer>();
{
auto client = std::make_shared<Client>(timer);
// .. some code
// client dies here, there is a race between the client callback and the client destructor
}
}
The client class subscribes a callback function to the periodic timer. Once the client object goes out of scope, there is a race condition between the client's callback and the client's destructor. The callback may be invoked with a dangling pointer!
The solution: using enable_shared_from_this to extend the object lifetime for the duration of the callback invocation.
struct Client : std::enable_shared_from_this<Client>
{
Client(std::shared_ptr< AsynchronousPeriodicTimer> timer)
: _timer(timer)
{
}
void Init()
{
auto captured_self = weak_from_this(); // weak_ptr to avoid cyclic references with shared_ptr
_timer->SetCallback(
[captured_self]
()
{
if (auto self = captured_self.lock())
{
// 'this' is guaranteed to be non-nullptr. we managed to promote captured_self to a shared_ptr
std::cout << ++self->_counter << '\n';
}
}
);
}
~Client()
{
// the destructor cannot be called while the callback is running. shared_ptr guarantees this
_timer->ClearCallback();
}
int _counter = 0;
std::shared_ptr< AsynchronousPeriodicTimer> _timer;
}
The mechanism of enable_shared_from_this, combined with the inherent thread safety of std::shared_ptr reference counting, enable us to ensure that the Client object cannot be destructed while the callback code is accessing its internal members.
Note that the Init method is separated from the constructor since the initialization process of enable_shared_from_this is not finalized until the constructor exits. Hence the extra method. It is generally unsafe to subscribe an asynchronous callback from within a constructor since the callback may access uninitialized fields.
Note that using a boost::intrusive_ptr does not suffer from this problem.
This is often a more convenient way to get around this issue.
It's exactly the same in c++11 and later: It is to enable the ability to return this as a shared pointer since this gives you a raw pointer.
in other word, it allows you to turn code like this
class Node {
public:
Node* getParent const() {
if (m_parent) {
return m_parent;
} else {
return this;
}
}
private:
Node * m_parent = nullptr;
};
into this:
class Node : std::enable_shared_from_this<Node> {
public:
std::shared_ptr<Node> getParent const() {
std::shared_ptr<Node> parent = m_parent.lock();
if (parent) {
return parent;
} else {
return shared_from_this();
}
}
private:
std::weak_ptr<Node> m_parent;
};