c++ std::thread on stack - c++

I have an object with a normal constructor. The constructor has a lot of initialization to do. Much of this initialization can be performed asynchronously, so I am calling a new thread from within the constructor.
When the thread in initialized on the stack, it appears that the thread is destroyed when the constructor exits which causes a crash. This would look like so:
class MyObject
{
MyObject()
{
// Typical initialization
// ...
// Time consuming initialization
std::thread(&MyObject::Init; this); // Create new thread to call Init();
// Crash when exit MyObject() here
}
void Init()
{
// Time consuming operations
}
};
The alternative (which works) is to create the thread on the heap as such.
class MyObject
{
std::thread* StartupThread;
MyObject()
{
// Typical initialization
// ...
// Time consuming initialization
StartupThread = new std::thread(&MyObject::Init; this); // Create new thread to call Init();
// Crash when exit MyObject() here
}
~MyObject()
{
StartupThread->join();
delete StartupThread;
}
void Init()
{
// Time consuming operations
}
};
My Question
Is there any harm is leaving the unjoined & undisposed thread object alive for the lifetime of the object or should I try to clean it up as soon as Init() finishes?
Is there a way to "automatically" dispose the thread when it finishes so it isn't left hanging around?
Essentially, can I get the thread on the stack in some way without it crashing as I described?

What about:
class MyObject
{
MyObject ()
{
f = std::async (std::launch::async, &MyObject::Init, this);
}
private:
void Init ();
std::future<void> f;
};
This allows you to do f.get () when you want to synchronize on the task. The destructor will join automatically if it is the last living copy of the object (you may want to delete the copy constructor if you don't want this behavior).
Note that you want to synchronize at some point before destruction, since if Init throws an exception, your destructor will.
Also, see this if you want to go the detach route.

You can call std::thread::detach() from the stack, but this is very dangerous considering the object could be long deleted while it's still running.
According to your requirements, the best option is to make sure it joins at the end of both Init() and the de-constructor. I think the better design is to join() at the end of the constructor for simplicity. Assuming there's no other processing to be done once you start the thread and when Init() is invoked, this would be the best choice.

Related

C++ std::shared_ptr custom deleter thread safety

[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).

Is it safe to use a boost::signals2::scoped_connection object as member of a class for automatic connection lifetime?

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.

How do I put a thread in a C++ smart pointer?

I want to create a C++ class with a thread doing some work once a minute.
First, may I define a thread as a variable member?
class my_class
{
public:
my_class()
: my_thread_(task, this)
{
}
~my_class()
{
done_ = true;
}
void run()
{
while(!done_)
{
...do work in the thread...
}
}
private:
static task(my_class * ptr)
{
ptr->run();
}
std::thread my_thread_;
std::atomic<bool> done_ = false;
};
Second, may I instead use a smart pointer with the thread in it?
class my_class
{
public:
~my_class()
{
done_ = true;
}
void init()
{
my_thread_.reset(new std::thread(task, this));
}
void run()
{
while(!done_)
{
...do work in the thread...
}
}
private:
static task(my_class * ptr)
{
ptr->run();
}
std::unique_ptr<std::thread> my_thread_;
std::atomic<bool> done_ = false;
};
It seems to me that I need to join with the child thread before it can be destroyed, but I am wondering whether the destructor of std::thread knows to do that safely.
You can put std::threads where ever you want, they are not special. Destroying thread handles is problematic. You can implicitly detach, implicitly kill or implicitly join and every option is bad. std::~thread (usually) just kills the whole program. To prevent that join or detach it.
Since you seem to want to implicitly join you may want to use std::async (probably with the std::launch::async policy) to launch your threads. It returns an std::future who's destructor implicitly joins.
it's possible to create std::unique_ptr<std::thread>. It will call std::thread destructor, when scope of unique_ptr will end. Remember that calling std::thread destructor is not terminating running thready gently, but by std::terminate. To end std::thread normally, you have to run .join() on std::thread object.
According to cppreference.com,
A thread object does not have an associated thread (and is safe to
destroy) after
it was default-constructed
it was moved from
join() has been called
detach() has been called
So if you define the thread as a member variable and write your destructor like this:
~my_class()
{
done_ = true;
my_thread_.join();
}
everything is fine, because it is guaranteed by the standard that the std::thread destructor will be called only after the my_class destructor, see this Q/A.

C++ constructor thread safety

Let's say I have a member variable vector initialised in the constructor, and this vector is read (not written to anywhere else) in several other member functions. Would I need to protect access to the vector (including in the constructor), or is it guaranteed that the object will be fully initialised and flushed to main memory before it's used in other threads?
Let me provide an example:
class A
{
public:
A();
void f1();
void f2();
private:
std::vector<int> v;
};
A::A()
{
// do some setup work in v
v.push_back(1);
}
// called from thread1
void A::f1()
{
// some readonly work on v
for (auto i : v) {
// do something on i
}
}
// called from thread2
void A::f2()
{
// more readonly work on v
if (v.empty()) {
// do other work
}
}
Do I need to lock-protect v in A::A(), A::f1() and A::f2()?
An object is created by a single thread, so you never have to worry about thread safety when running code inside the constructor that touches member variables. However, if you are using static variables within the constructor then you may need to add some form of locking around the access.
There is an edge case where code within a constructor can be called by multiple threads, and this is when you are using either placement new. For example, let's say you've got a buffer somewhere, and you're going to allocate an object into it:
byte buffer[100];
Foo *foo = new (buffer) Foo;
Here, unless you are locking around the call to new then it's possible for two or more constructors to run in parallel as they're running against the same block of memory. However, this is a real specialized edge-case and would require special handling (eg locking around the placement-new construction).
An object is constructed by a single thread.
Other threads can access the object only by means of the instance reference.
In other words, the object's constructor will have finished its work before other threads call a method.
You therefore don't need to implement thread-safe code within a constructor.
Of course, in case another object is passed to the constructor as a parameter, eventual access to that object within the constructor, should be thread-safe.
As stated in the other answers, there is no point in implementing synchronization primitives in the constructer, but that doesn't mean you can't have a race, if you don't synchronize externally:
std::atomic<A*> g_ptr = nullptr;
void threadFun1() {
g_ptr.store(new A{}, std::memory_order_relaxed);
}
void threadFun2() {
A* l_ptr = nullptr;
while (l_ptr == nullptr) {
l_ptr = g_ptr.load(std::memory_order_relaxed);
}
l_ptr->f1();
}
In above code, you have a data race between the constructor of A and f1. The problem is that - without synchonization - from the point of view of thread2, g_ptr might be written before the object is completely constructed.
However, there is nothing you can do inside the constructor to prevent this kind of race. Instead you have to use external means of synchronization, like using non-relaxed memory ordering for the atomic load and store operations or starting thread2 from within thread1 after the global variable is set.
Take this code example below:
model.h
namespace Stackoverflow {
class Model {
public:
Model();
~Model();
std::vector<int> *integers() const { return _integers.get(); }; // read only
private:
std::unique_ptr<std::vector<int>> _integers; // registered before constructor
};
}
model.cpp
Stackoverflow::Model::Model() {
_integers = std::make_unique<std::vector<int>>(); // initialized
}
Stackoverflow::Model::~Model() {
_integers.release();
}
The private member "_integers" will be registered but not initialized until the constructor is being called by the caller.
Stackoverflow::Model stackoverflow;
When another thread want to access this vector, call the getter.
auto *vector = stackoverflow.integers();
The member will be fully initialized when the caller is actually asking for the vector.

An object acquiring mutex in destructor to prevent deletion of itself

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.