I've written a sample program to show my problem - I don't understand why firstVersion() is working properly, and secondVersion() gives me error :terminate called without an active exception Aborted. Thanks for answers!
Here's the code :)
#include <thread>
#include <iostream>
#include <chrono>
using namespace std;
const int threadCount = 100;
int N = 1;
void f() {
N++;
}
void firstVersion() {
thread * t[threadCount];
for(int i = 0; i < threadCount; i++) {
thread * ti = new thread{f};
t[i] = ti;
}
for(int i = 0; i < threadCount; i++) {
t[i]->join();
delete t[i];
}
}
void secondVersion() {
thread * t[threadCount];
for(int i = 0; i < threadCount; i++) {
thread ti{f};
t[i] = &ti;
}
for(int i = 0; i < threadCount; i++)
t[i]->join();
}
int main() {
//firstVersion();
secondVersion();
return 0;
}
The second version fails because the lifetime of thread ends at the end of your for loop before you call join().
void secondVersion() {
thread * t[threadCount];
for(int i = 0; i < threadCount; i++) {
thread ti{f}; // local object of thread
t[i] = &ti;
} // the object dies without a join()
Your example can be simplified as:
void SomeFunc() {}
int main()
{
std::thread* tp;
//{
std::thread t{SomeFunc};
tp= &t;
//} // if the closing brace is present, object t calls destructor here!
tp->join();
}
If you take a look into your STL you find the following code:
~thread()
{
if (joinable())
std::terminate();
}
That simply results in the call to the terminate.
So the example code has two mistakes:
1) Create a pointer to an object which dies before the pointer is used which is called dangling reference
2) Because thread object dies before join() was called, it simply calls terminate.
a std::thread needs to be joined or detached before its destructor runs.
since you didn't call any detach or join the std::thread's destructor called std::abort.
in the first example, you first joined the thread before actually calling its destructor (via delete):
t[i]->join();
delete t[i];
luckily for you, it prevented something much more worse: dangling pointers. in the end of each
for(int i = 0; i < threadCount; i++) {
thread ti{f};
t[i] = &ti;
}
ti is dead, you keep a pointer to an object which does not live anymore. you violate some basic rule of C++ never return or keep a pointer or reference to local variable outside its scope
Related
I'm new to c++ and don't know how to let main thread wait for all async threads done. I refered this but makes void consume() not parallel.
#include <iostream>
#include <vector>
#include <unistd.h> // sleep
#include <future>
using namespace std;
class Myclass {
private:
std::vector<int> resources;
std::vector<int> res;
std::mutex resMutex;
std::vector<std::future<void>> m_futures;
public:
Myclass() {
for (int i = 0; i < 10; i++) resources.push_back(i); // add task
res.reserve(resources.size());
}
void consume() {
for (int i = 0; i < resources.size(); i++) {
m_futures.push_back(std::async(std::launch::async, &Myclass::work, this, resources[i]));
// m_futures.back().wait();
}
}
void work(int x) {
sleep(1); // Simulation time-consuming
std::lock_guard<std::mutex> lock(resMutex);
res.push_back(x);
printf("%d be added.---done by %d.\n", x, std::this_thread::get_id());
}
std::vector<int> &getRes() { return res;}
};
int main() {
Myclass obj;
obj.consume();
auto res = obj.getRes();
cout << "Done. res.size = " << res.size() << endl;
for (int i : res) cout << i << " ";
cout <<"main thread over\n";
}
Main thread ends up when res = 0. I want obj.getRes() be be executed when all results be added into res.
Done. res.size = 0
main thread over
4 be added.---done by 6.
9 be added.---done by 11...
You had the right idea with the commented out line: m_futures.back().wait();, you just have it in the wrong place.
As you note, launching a std::async and then waiting for its result right after, forces the entire thing to execute in series and makes the async pointless.
Instead you want two functions: One, like your consume() that launches all the async's, and then another that loops over the futures and calls wait (or get, whatever suits your needs) on them - and then call that from main.
This lets them all run in parallel, while still making main wait for the final result.
Addition to #Frodyne 's answer,
consume() function calls are parallel, and main thread waits for the all consume() s have their work done;
void set_wait(void)
{
for (int i = 0; i < resources.size(); i++) {
m_futures[i].wait();
}
}
And call it here
void consume() {
for (int i = 0; i < resources.size(); i++) {
m_futures.push_back(std::async(std::launch::async, &Myclass::work, this, resources[i]));
// Calling wait() here makes no sense
}
set_wait(); // Waits for all threads do work
}
I created new function for convenience.
You can use std::future:wait after you add task to m_futures. Example.
void consume() {
for (int i = 0; i < resources.size(); i++) {
m_futures.push_back(std::async(std::launch::async, &Myclass::work, this, resources[i]));
//m_futures.back().wait();
}
for(auto& f: m_futures) f.wait();
}
This question already has an answer here:
Why does this C++ thread code trigger an abort() error?
(1 answer)
Closed last year.
Mainly for test purposes,
I want to run a member function on a thread.
Endless tries - and still, only error messages,
Please - can anyone explain the cause of the error and some best practices of doing so?
Thanks
#include <thread>
#include <iostream>
using namespace std;
class Test {
public:
int x = 1;
int y = 7;
int a() {
for (int i = 1; i < 1000; i++) {
x += y;
cout << "x:" << x << endl;
}
return x;
}
int b() {
for (int i = 1; i < 1000; i++) {
y -= 0.5 * x;
cout << "y:" << y << endl;
}
return y;
}
Test() {
}
Test* run() {
thread(&Test::a, this);
//thread(&Test::b, this);
return this;
}
};
int main()
{
Test* obj = new Test();
obj->run();
return 0;
}
Your std::thread object lives only until the end of the expression in which it is created as a temporary. When it is destroyed and the thread is still in a joinable state, std::terminate is called, which aborts your program.
You should store the std::thread object somewhere (e.g. in the Test object or in main or locally in run) and call .join() on it at the correct time where you expect the thread to finish (e.g. destructor or before the end of main or at the end of run).
Aside from that, if you run the out-commented thread as well, you have data races causing undefined behavior. You may not access non-atomic objects (such as x and y) in multiple threads without synchronization if at least one of these accesses is a write.
I'm trying to run a multi-threaded job queue in c++. As an example I have tested the following program:
#include <thread>
#include <mutex>
#include <list>
#include <vector>
class Job
{
public:
void Run(void)
{
}
};
class Queue
{
private:
std::recursive_mutex mtxJobs;
std::list<Job *> mJobs;
public:
Job *Take(void)
{
std::scoped_lock(mtxJobs);
if (mJobs.size() > 0)
{
Job *pJob(mJobs.front());
mJobs.pop_front();
return pJob;
}
else
return NULL;
}
void Add(Job *pJob)
{
std::scoped_lock(mtxJobs);
mJobs.push_back(pJob);
}
size_t Size(void)
{
std::scoped_lock(mtxJobs);
return mJobs.size();
}
};
void Work(Queue &q)
{
Job *pJob;
while ((pJob = q.Take()) != NULL)
{
pJob->Run();
delete pJob;
}
}
int main()
{
size_t i;
Queue q;
for (i = 0; i < 1000; i++)
q.Add(new Job);
std::vector<std::thread> threads(4);
for (i = 0; i < 4; i++)
threads[i] = std::thread(Work, std::ref(q));
for (i = 0; i < 4; i++)
threads[i].join();
return 0;
}
When I run it like this:
g++ -std=c++17 -lpthread test.cpp -o test && ./test
it crashes with a SEGFAULT. Does anyone have any idea why?
GDB indicates that the crash always occurs when the list 'mJobs' is accessed. However, the locks should prevent concurrent modification right?
Can anyone help me?
You are accessing your queue without synchronization:
std::scoped_lock(mtxJobs);
this is local variable with name mtxJobs which is created taking no arguments and hides your mutex mtxJobs member. When scoped_lock is created without arguments it does nothing according to reference.
You need to write:
std::scoped_lock lock(mtxJobs);
now, your mutex is locked in ctor of scoped_lock object.
I've been trying to solve a problem concurrently, which fits the thread pool pattern very nicely. Here I will try to provide a minimal representative example:
Say we have a pseudo-program like this:
Q : collection<int>
while (!Q.empty()) {
for each q in Q {
// perform some computation
}
// assign a new value to Q
Q = something_completely_new();
}
I'm trying to implement that in a parallel way, with n-1 workers and one main thread. The workers will perform the computation in the inner loop by grabbing elements from Q.
I tried to solve this using two conditional variables, work, on which the master threads notifies the workers that Q has been assigned to, and another, work_done, where the workers notify master that the entire computation might be done.
Here's my C++ code:
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
using namespace std;
std::queue<int> Q;
std::mutex mut;
std::condition_variable work;
std::condition_variable work_done;
void run_thread() {
for (;;) {
std::unique_lock<std::mutex> lock(mut);
work.wait(lock, [&] { return Q.size() > 0; });
// there is work to be done - pretend we're working on something
int x = Q.front(); Q.pop();
std::cout << "Working on " << x << std::endl;
work_done.notify_one();
}
}
int main() {
// your code goes here
std::vector<std::thread *> workers(3);
for (size_t i = 0; i < 3; i++) {
workers[i] = new std::thread{
[&] { run_thread(); }
};
}
for (int i = 4; i > 0; --i) {
std::unique_lock<std::mutex> lock(mut);
Q = std::queue<int>();
for (int k = 0; k < i; k++) {
Q.push(k);
}
work.notify_all();
work_done.wait(lock, [&] { return Q.size() == 0; });
}
for (size_t i = 0; i < 3; i++) {
delete workers[i];
}
return 0;
}
Unfortunately, after compiling it on OS X with g++ -std=c++11 -Wall -o main main.cpp I get the following output:
Working on 0
Working on 1
Working on 2
Working on 3
Working on 0
Working on 1
Working on 2
Working on 0
Working on 1
Working on 0
libc++abi.dylib: terminating
Abort trap: 6
After a while of googling it looks like a segmentation fault. It probably has to do with me misusing conditional variables. I would appreciate some insight, both architectural (on how to approach this type of problem) and specific, as in what I'm doing wrong here exactly.
I appreciate the help
Your application was killed by std::terminate.
Body of your thread function is infinite-loop, so when these lines are executed
for (size_t i = 0; i < 3; i++) {
delete workers[i];
}
you want to delete threads which are still running (each thread is in joinable state). When you call destructor of thread which is in joinable state the following thing happens (from http://www.cplusplus.com/reference/thread/thread/~thread/)
If the thread is joinable when destroyed, terminate() is called.
so if you want terminate not to be called, you should call detach() method after creating threads.
for (size_t i = 0; i < 3; i++) {
workers[i] = new std::thread{
[&] { run_thread(); }
};
workers[i]->detach(); // <---
}
Just because the queue is empty doesn't mean the work is done.
finished = true;
work.notify_all();
for (size_t i = 0; i < 3; i++) {
workers[i].join(); // wait for threads to finish
delete workers[i];
}
and we need some way to terminate the threads
for (;!finshed;) {
std::unique_lock<std::mutex> lock(mut);
work.wait(lock, [&] { return Q.size() > 0 || finished; });
if (finished)
return;
This is my code for multi threading (This is not the actual code but parts of different files at one place where I feel I am doing something wrong)
//main function
Example ExampleObj;
for (int i=0;i<10;i++)
{
pthread_t *service_thread = new pthread_t;
pthread_create(service_thread, NULL,start,&ExampleObj);
}
//start function
void *start(void *a)
{
Example *h = reinterpret_cast<Example *>(a);
h->start1();
return 0;
}
class Example
{
public:
void start1()
{
std::cout <<"I am here \n";
}
};
Code is not giving any error but it's not coming to start1 function as well.
Please let me know if I am creating the threads correctly or not.
If not, then what is the correct way.
There is no code that stops your main() from terminating the process before your worker threads have completed.
main() should look something like:
int main() {
Example ExampleObj;
// Start threads.
pthread_t threads[10];
for(size_t i = 0; i < sizeof threads / sizeof *threads; ++i) {
pthread_create(threads + i, NULL,start,&ExampleObj);
}
// Wait for the threads to terminate.
for(size_t i = 0; i < sizeof threads / sizeof *threads; ++i) {
pthread_join(threads[i], NULL);
}
}