Assume I have class A with resource B. Class A has a function that does not acquire a mutex lock before I want to destroy it. I call boost::shared_ptr::reset() to destroy instance of class A. Is resource B guaranteed to be destroyed at that point?
class Resource{
public:
Resource(){ }
~Resource(){ free(); }
void init() {}
void free() {}
};
class A{
public:
A(){ B.init(); }
~A(){}
void functionC(){
boost::lock_guard<boost::mutex> lock(Mutex);
// Stuck forever
boost::lock_guard<boost::mutex> lock2(Mutex);
}
private:
boost::mutex Mutex;
Resource B;
};
main(){
boost::shared_ptr<A> pointer(new A());
// Do a function call that gets stuck but allows main thread to continue
boost::thread t(boost::bind(&A::functionC, *pointer));
pointer.reset();
// Loop forever
while(1);
}
To be specific, I want function B::free() to be called at the point in which I call pointer.reset(). Is this code guaranteed to do that, or do I have to explicitly call it somewhere? Obviously I don't want to be as explicit as
pointer->freeB();
pointer.reset();
In your scenario, B is a member of A. It will get destroyed (and free() will be called) when A gets destroyed. No need for an explicit call.
However in your code, there's no guarantee that your pointer.reset() the allocated A object gets destroyed: it only gets destroyed if pointer was the only shared_ptr pointing to this object, i.e. no copy of the pointer was made since its creation (there 's no evidence of that here, but to be checked in your real code).
By the way, there's a t.join() missing in your code.
Related
[edited with a more concrete example]
Suppose I have a thread-safe object (all public member use a mutex) and a shared_ptr with a custom deleter, like so:
class A {
public:
void update(int x);
void print_sum();
...
}
class AContainer {
private SomeConcurrentMap<string, shared_ptr<A>> aMap;
void newA(string name) {
aMap.emplace(name, shared_ptr<A>(new A, [](A *p){p->print_sum(); delete p;}));
}
void finalizeA(string name) {
aMap.erase(name);
}
shared_ptr<A> getA(string name) const {
// fixme handle case of not found...
return aMap.find(name).second;
}
};
void someFunctionInSomeThread(const AContainer &cont, string name, int c) {
// fixme handle case of not found...
cont.getA(name)->update(c);
}
Let's assume all A operation are protected by a mutex, and that SomeConcurrentMap is thread-safe. The usage is scenario is:
call AContainer::newA() from any thread
call someFunctionInSomeThread() multiple times by multiple threads
call AContainer::finalizeA() from any thread - possibly in parallel to step 2
And the idea that A::print_sum() is called after both step 3 completed and all running A::update() operations complete.
Is it safe to assume that by the time p->print_sum() is called, all the A::update() operations on the object have been called?
Is it safe to assume that by the time p->print_sum() is called, all the A::update() operations on the object have been called?
Yes, it is safe to assume that. Only one thread is going to call the destructor, and no thread is going to call the destructor before calling other member functions of A (such a thread would be invoking UB even if no other threads existed, e.g. by keeping a raw pointer after destroying the shared pointer and then accessing the object via the raw pointer).
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 have the following class structure, which initially threw a segfault. I have fixed the problem, but don't fully understand why the code initially through a segfault. I had a class B, a subclass of A, which,
after A initialised an object (InternalA) in the initialisation list
of the constructor, called a Run() method, which called a method on InternalA (InternalA.Start()) before calling a blocking method (io_service_.Run()), and so B's constructor never actually returned.
A separate thread would then try to access B, and call B->SendMsg(), but
all of InternalA's internal state would be corrupted. I fixed the problem by removing the blocking Run() method call from the constructor, and calling it afterwards.
Code shows me that the InternalA object does indeed get correctly initialised, but when calling b->SendMsg, InternalA is completely corrupted.
The issue that, using the new operator, the "real" address only gets assigned to the B* pointer after the constructor is returned (even though, when I check the address of b in the main thread, it is no longer null). If I instead malloced B, and subsequently called *b = B(), would it still be an issue, or would this then be architecture specific?
class B: public A
{
B(): A(arg1, arg2) { Run(); }
};
class A {
A(): InternalA()... {}
Run() {
InternalA.Start();
// Method does not terminate
io_service_.Run();
}
};
class InternalA {
InternalA(): io_service_(), map_(), id_(5) {}
void Start() {
std::cout << connections_.size() << std::endl;
}
void SendMsg() {
std::cout << connections_.size() << std::endl;
}
private:
boost::asio io_service_
std:map<X,Y> map_;
int id_;
};
int main() {
B* b = null;
std::thread t([&b] {b = new B()}); // Run() method gets called
usleep(200000);
b->SendMsg(); // All objects in InternalA are corrupted (point to invalid addresses
}
Before you can assign a value to b, that value has to be computed first. In your case, this computation (new B()) never returns, so you read uninitialized contents of the b in another thread.
Also, "a separate thread would then try to access B"? Without any checks organized to see if that "B" is actually there? You will have many hard-to-find bugs with such an approach.
Can this concept work?
class MyClass
{
public:
~MyClass()
{
MyMutex.acquire();
}
void ThreadFunction(void* param)
{
MyMutex.acquire();
//do something
MyMutex.release();
}
};
Also Let's say we have an object of this class, call it "inst"
What I am trying to achieve is that if:
One thread is active and executes inst->ThreadFunction
Another Thread is calling delete inst then this call will hang until ThreadFunction releases the mutex.
Is that ok to do?
It would be much better to create a wrapper around MyClass if MyClass contains resources. Its even worse if the program uses a class that inherits from MyClass, because the destructor for ChildofMyClass will have already been called by this point.
A question about boost::shared_ptr here:
I have 3 Classes.
A is some kind of Main class which is responsible to manage everything.
B is a class which just has functions to do some work.
Dispatcher is just a class which wraps around a seperate thread, which gets the work from Instaces of Bdone in this thread.
So it is kinda working like this: A has an instance of Dispatcher. Now on occassion A generates an instance of B and passes it to the dispatcher.
The important part is, that B needs to call A::callback() when it's done. This is why B gets a reference to A in it's constructor ( see code below )
A.hpp
class A : public boost::enable_shared_from_this<A>
{
public:
A();
void sendB();
void callback();
private:
Dispatcher m_Dispatcher;
};
B.hpp
class B
{
public:
B(boost::shared_ptr<A> ptr);
boost::shared_ptr<A> m_PointerToA;
/* Some other functions */
};
Dispatcher.hpp
class Dispatcher
{
public:
void run();
void dispatch(boost::shared_ptr<B> b);
private:
void doWork();
boost::thread m_Thread;
};
A.cpp
A::A()
{
m_Dispatcher.run();
}
void A::sendB()
{
boost::shared_ptr ptr_B;
ptr_B.reset(new B(this->shared_from_this);
m_Dispatcher.dispatch(ptr_B);
}
B.cpp
B::B(boost::shared_ptr<A> ptr) :
: m_PointerToA(ptr)
{
}
main_example.cpp
int main()
{
A instanceA;
while(true)
{
instanceA.sendB();
/* Do some other stuff */
}
return 0;
}
So my question is:
Is it reasonable to use boost::shared_ptr for this purpose?
I am not sure if the shared_ptr is the right thing to go here. My problem is, that I don't know what happens exactly when I call the constructor from B and pass it the this pointer. Now according to shared_ptr I would assume that m_PointerToA takes ownership of A. But this would mean that when the work in the Dispatcher is done and my instance of B gets deleted it would also delete the reference to m_PointerToA which would actually mean it kills the object itself despite the fact there is an actual instance of A in the main loop.
Update:
Added some code and updated question itself to make it more clear.
There's nothing particular wrong with this design. However I would prefer to instead use boost::function<> & boost::bind. It gives you way better flexibility for the callback and doesn't tie B as tightly to A. Of course you still have to be vary of the usual threading caveats.
Yes, it is okay to just copy/assign a shared_ptr, it will only increase the reference count.
In your example, shared_from_this() will create a (here: temporary) shared_ptr from the weak_ptr that is hold by this (ref count 1), so when you assign/copy-construct m_PointerToA, the reference count will increase temporarily to 2 before the ctor returns and the temporary object will be destroyed, decreasing the reference count to 1 again (the shared_ptr is "aware" of the one instance in your B object).
So, yes, if B is deleted, it will destroy A in this case (as the reference count drops to 0).
Your concern
This would mean if my Instance of B is deleted, it would also delete m_PointerToA which would also kill my instance of A . Of course my original instance of A is held elsewhere.
only shows that if you plan/need/intend to keep a pointer to the instance of A for further usage, you should do so with a shared_ptr as well instead of a raw pointer. If you have control of A's interface, the easiest way would be a named constructor like this:
class A : public boost::enable_shared_from_this<A> {
public:
static boost::shared_ptr<A> create();
void initClassB();
// ....
private:
A();
A( const A & other );
A& operator=( const A & rhs );
};
boost::shared_ptr<A> A::create() {
return boost::shared_ptr<A>( new A() );
}
Then, even if your instance of B is deleted, the instance of A will still survive because the reference count of the shared_ptr is still (at least) 1.