C++ thread program doesn't terminate - c++

I have no idea why my code doesn't terminate.
It is probably some obvious thing I miss here, please help!
using namespace std;
int main(int argc, char* argv[])
{
MyClass *m = new MyClass();
thread t1(th,m);
delete m;
m=NULL;
t1.join();
return 0;
}
void th(MyClass *&p)
{
while(p!=NULL)
{
cout << "tick" << endl;
this_thread::sleep_for(chrono::seconds(1));
}
return;
}

The thread is being given a copy of m, not a reference to it. Use a reference wrapper to give it a reference:
thread t1(th,std::ref(m));
The program will probably end as expected then; but you still have undefined behaviour due to the data race of modifying m on one thread, and reading it on another without synchronisation. To fix that, either use std::atomic<MyClass*>, or protect both accesses with a mutex.

Related

Parameter reference works on lambda but not in function

I'm not too sure if I'm just completely forgetting basics here but can someone please tell me why after changing the flag only T1 stops?
#include <thread>
#include <iostream>
void job(const bool &flag)
{
using namespace std::chrono_literals;
while (flag)
{
std::cout << "Working T2" << '\n';
std::this_thread::sleep_for(1s);
}
}
int main(int argc, char const *argv[])
{
bool flag = true;
std::thread t1([&flag]()
{
using namespace std::chrono_literals;
while (flag)
{
std::cout << "Working T1" << '\n';
std::this_thread::sleep_for(1s);
}
});
std::thread t2(job, flag);
std::cin.get();
flag = false;
t1.join();
t2.join();
return 0;
}
my understanding is that both are accessing the same piece of memory as the flag is being passed as a reference, so the job function should not be creating it's own copy of the flag, and should just access the same flag passed to it, is this not how this works?
Many Thanks
std::thread t2(job, flag);
This makes a copy of flag and passes that copy to job(). In order to use a reference, you need to use std::ref:
std::thread t2(job, std::ref(flag));
But why is this a requirement?
There's a few different ways to look at it, but here's a fairly straightforward counter-example:
void job(const bool& val);
int main() {
// No problem
job(true);
// Would be broken if std::thread didn't make a copy.
std::thread my_thread(job, true);
}
Just so all the relevant information is in one place:
why after changing the flag only T1 stops?
Firstly, because std::thread copies its arguments by value, as you see from the linked documentation. So, the existing code is guaranteed not to work
If you fix this by wrapping the argument in std::ref as suggested, you reach the second problem (which is actually already present in your lambda version), which is:
Secondly because using this reference in another thread this way is a data race. So, the existing code is guaranteed not to be portable. It may happen to work for some platforms, some of the time, but it's still sloppy.
The flag should be a std::atomic<bool> (or std::atomic_flag) instead.

no crash if I reset the same shared_ptr in multi-threads

I just want to confirm it's safe to reset to the same smart pointer with lock in multi-threads? if there is no lock_guard, it's not safe due to it is not a thread-safe method? I suppose reset is not threadsafe, however, no crash is observed if I removed the lock.
class foo {
public:
foo()
{
std::cout << "foo constructed" << std::endl;
}
~foo()
{
std::cout << "foo destructed" << std::endl;
}
};
int main(int argc, const char * argv[]) {
std::shared_ptr<foo> f = std::make_shared<foo>();
conqueue = dispatch_queue_create("MyConcurrentDiapatchQueue", DISPATCH_QUEUE_CONCURRENT);
static std::mutex io_mutex;
for (int i = 0; i < 100000; i++)
{
dispatch_async(conqueue, ^{
std::lock_guard<std::mutex> lk(io_mutex); // no crash without this line as well
f.reset(); // it's safe? No crash if I reset the same shared_ptr in multi-threads.
});
}
return 0;
}
The shared_ptr object is not thread-safe, nor is the pointed-to object. Only the reference count is thread-safe. So yes, you need to use a guard.
In C++20, there is std::atomic<std::shared_ptr<T>>.
Documentation don't guarantee safety of that component. Essentially if standard says nothing about it then your assumption is right. You have to have that lockquard or anything that provides same functionality.
Crash might be no observable because you don't have racing condition until you try read pointer in a concurrent thread because you don't actually try to use that value (all that reset does is to change pointer value).
Well and you can't rely on that you can't observe an UB, UB is a Schrodinger's cat.

How to return a result from a thread by reference?

It is possible to pass an argument to a function running in another thread, by reference.
Is it possible to return a result from a function running in another thread, by reference. If so, how?
It is possible to pass an argument to a function running in another
thread, by reference.
Not directly, because all arguments are copied or moved into the other thread, but you can simulate reference passing with std::ref or std::cref. See std::thread constructor documentation:
The arguments to the thread function are moved or copied by value. If
a reference argument needs to be passed to the thread function, it has
to be wrapped (e.g. with std::ref or std::cref).
And of course, you have to make sure that the referenced object isn't destructed before the other thread is done using it.
Here's a small example:
#include <iostream>
#include <thread>
void f(int& x)
{
std::cout << x << '\n';
}
int main()
{
int a = 1;
std::thread t(f, std::ref(a));
t.join();
// safe, because `a` still exists at this point,
// but the thread is already finished
}
Is it possible to return a result from a function running in another
thread, by reference.
No.
First of all, that wouldn't make sense, because it would defeat the purpose of threads if the caller was blocked waiting for the called function to return (however, see below).
Second, that's just not how threads work. As the C++ standard says at ยง4.7/1 [intro.multithread]:
When one thread creates another, the initial call to the top-level
function of the new thread is executed by the new thread, not by the
creating thread.
In other words, every thread has "its own stack". This is completely different from using functions in the same thread. You cannot use return to return anything from a new thread to the original thread.
You indirectly "return" something by the other thread setting data accessible to the original thread. You can do that via a simulated reference if you want to:
#include <iostream>
#include <thread>
void f(int& x, int& result)
{
result = x * x;
}
int main()
{
int a = 2;
int result;
std::thread t(f, std::ref(a), std::ref(result));
t.join();
std::cout << result << '\n';
}
Outside of such toy examples, the shared data will more realistically be a std::atomic or be guarded by std::mutex / std::scoped_lock et al.
That being said, you should definitely have a look at std::future. Futures don't change the way threads work internally, but they provide an abstraction layer which resembles a normal function-call stack.
Yes, but be very be careful cause each thread may using the same resource and leading to "data racing". You should use "mutex" or another mechanism to synchronize
Ex: Without mutex
#include<iostream>
#include<string>
#include<vector>
#include<thread>
static std::vector<std::string> glm;
void addMap(std::vector<std::string> &glm, std::string name)
{
glm.push_back(name);
std::cout << "Add: " << name << "\n";
}
int main()
{
std::thread t[4];
std::vector < std::string> names = { "Hellen", "Peter", "Bob", "Zoe" };
for(int i = 0; i < names.size(); i++)
{
t[i] = std::thread(addMap, std::ref(glm), std::ref(names[i]));
}
for(int i = 0; i < names.size(); i++)
{
t[i].join();
}
}
As the example above, we expect it will print:
Add: Hellen
Add: Peter
Add: Bob
Add: Zoe
But it's NOT. Sometimes, it will print not enough names, sometimes the order is different.
Example with mutex:
#include<iostream>
#include<string>
#include<vector>
#include<thread>
#include<mutex>
static std::vector<std::string> glm;
std::mutex mut;
void addMap(std::vector<std::string> &glm, std::string name)
{
mut.lock();
glm.push_back(name);
std::cout << "Add: " << name << "\n";
mut.unlock();
}
int main()
{
std::thread t[4];
std::vector < std::string> names = { "Hellen", "Peter", "Bob", "Zoe" };
for(int i = 0; i < names.size(); i++)
{
t[i] = std::thread(addMap, std::ref(glm), std::ref(names[i]));
}
for(int i = 0; i < names.size(); i++)
{
t[i].join();
}
}
Be very careful when coding with multithread

Very simple method with QtConcurrentRun and mutex sometimes gives segmentation fault

I want to know what is wrong with this code. Sometimes I get sementation fault, sometimes not. This is a problem that I have in a greater piece of software, the idea is that just one thread at the same time is executing the method MyClass::print. Even with this simple example, it fail with segmentation fault. What is wrong in the code? How I can solve the problem?
Thanks!
#include <iostream>
#include <ctime>
#include <QMutex>
#include <QtConcurrentRun>
class MyClass : QThread {
public:
void print(std::string str) {
mutex.lock();
std::cout << "In some thread: " << str << "\n";
mutex.unlock();
}
private:
QMutex mutex;
};
int main() {
MyClass myCl;
for(int i=0; i < 10; i++) {
QtConcurrent::run(&myCl, &MyClass::print,std::string("bla"));
}
}
You do not join your threads after the for cycle that spawns them.
Therefore, the main() function may end before all the threads have finished. This would make myCl go out of scope, and the threads would be trying to access an object that has been destroyed (in particular, its mutex variable). Which gives you Undefined Behavior.
Things should get better if you joined your threads before exiting from main() (or find any other way of not exiting from main() as long as any of the threads is still running).

(simple) boost thread_group question

I'm trying to write a fairly simple threaded application, but am new to boost's thread library. A simple test program I'm working on is:
#include <iostream>
#include <boost/thread.hpp>
int result = 0;
boost::mutex result_mutex;
boost::thread_group g;
void threaded_function(int i)
{
for(; i < 100000; ++i) {}
{
boost::mutex::scoped_lock lock(result_mutex);
result += i;
}
}
int main(int argc, char* argv[])
{
using namespace std;
// launch three threads
boost::thread t1(threaded_function, 10);
boost::thread t2(threaded_function, 10);
boost::thread t3(threaded_function, 10);
g.add_thread(&t1);
g.add_thread(&t2);
g.add_thread(&t3);
// wait for them
g.join_all();
cout << result << endl;
return 0;
}
However, when I compile and run this program I get an output of
$ ./test
300000
test: pthread_mutex_lock.c:87: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
Aborted
Obviously, the result is correct but I'm worried about this error message, especially because the real program, which has essentially the same structure, is getting stuck at the join_all() point. Can someone explain to me what is happening? Is there a better way to do this, i.e. launch a number of threads, store them in a external container, and then wait for them all to complete before continuing the program?
Thanks for your help.
I think you problem is caused by the thread_group destructor which is called when your program exits. Thread group wants to take responsibility of destructing your thread objects. See also in the boost::thread_group documentation.
You are creating your thread objects on the stack as local variables in the scope of your main function. Thus, they have already been destructed when the program exits and thread_group tries to delete them.
As a solution, create your thread objects on the heap with new and let the thread_group take care of their destruction:
boost::thread *t1 = new boost::thread(threaded_function, 10);
...
g.add_thread(t1);
...
If you don't need a handle to your threads, try using thread_group::create_thread() which alleviates the need to manage the thread at all:
// Snip: Same as previous examples
int main(int argc, char* argv[])
{
using namespace std;
// launch three threads
for ( int i = 0; i < 3; ++i )
g.create_thread( boost::bind( threaded_function, 10 ) );
// wait for them
g.join_all();
cout << result << endl;
return 0;
}
add_thread() takes ownership of thread you pass in. Thread group deletes the thread. In this example you are deleting memory allocated on stack, pretty much a capital offence.
Member function add_thread()
void add_thread(thread* thrd);
Precondition:
The expression delete thrd is
well-formed and will not result in
undefined behaviour.
Effects:
Take ownership of the boost::thread
object pointed to by thrd and add it
to the group.
Postcondition:
this->size() is increased by one.
Not sure if that's what's wrong in your code, or if this is just example bug. Otherwise code looks fine.
It looks none of above actually answered the question.
I met the similar issue. The consequence of this warning (pthread_mutex_lock.c:87: __pthread_mutex_lock: Assertion `mutex->_data._owner == 0' failed.
Aborted) is that sometimes the program will leak threads and cause a boost_resource_error exception.
The reason looks like the program continues to execute after join_all() although most of threads are still running ( not terminated ).