#include <iostream>
#include <string>
#include <thread>
#include <future>
int main()
{
auto pms = std::promise<std::string>();
auto ftr = pms.get_future();
std::thread([&](){pms.set_value("hello world");});
ftr.wait();
std::cout << ftr.get() << std::endl;
return 0;
}
According to this link, std::future::wait blocks until the result becomes avaiable.
However, the code above can't print anything. Obviously the main thread has finished before the thread of pms.set_value finished.
Why doesn't ftr.wait() block?
The problem is not that std::future::wait doesn't block. The real problem is that you have a race condition between the thread that you spawned, doing it's work, and the destruction of std::thread (temporary) object in the main thread.
Because of that, abort is called in the destructor of std::thread if the thread is still joinable.
Working code:
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono>
int main()
{
auto pms = std::promise<std::string>();
auto ftr = pms.get_future();
std::thread thread ([&](){pms.set_value("hello world");});
ftr.wait();
std::cout << ftr.get() << std::endl;
thread.join ();
return 0;
}
Note, if you don't join the thread explicitly, you would still have the same race condition (since it's possible that main can do its work faster, than the thread can clean itself up.
Demo of working example: here.
Alternatively you can detach the thread and use promise::set_value_at_thread_exit rather than set_value
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono>
int main()
{
auto pms = std::promise<std::string>();
auto ftr = pms.get_future();
std::thread([&](){pms.set_value_at_thread_exit("hello world");}).detach();
ftr.wait();
std::cout << ftr.get() << std::endl;
return 0;
}
Related
I'm trying to do this simple program, where I want to use the take and append functions, which access a buffer implemented with a list, in a producer-consumer problem:
#ifndef buf_h
#define buf_h
#include <list>
using std::list;
#include <mutex>
using std::mutex;
#include <condition_variable>
using std::condition_variable;
class Buffer
{
public:
Buffer(int cap);
void append(int shift);
int take();
private:
list<double> Buffer_;
int capacity_;
int count_;
mutex mutex_;
condition_variable not_full_;
condition_variable not_empty_;
};
#endif
This is buffer:
#include "buf.h"
#include <list>
using std::list;
#include <mutex>
using std::mutex;
using std::unique_lock;
#include <condition_variable>
using std::condition_variable;
Buffer::Buffer(int capacity)
: Buffer_(capacity,0), capacity_{capacity}, count_{0}
{
}
void Buffer::append(int shift)
{
unique_lock<mutex> mlock(mutex_);
while(count_== capacity_)
not_full_.wait(mlock);
Buffer_.push_back(shift);
++count_;
not_empty_.notify_one();
}
int Buffer::take()
{
unique_lock<mutex> mlock(mutex_);
while(count_ == 0)
not_empty_.wait(mlock);
int w = Buffer_.front();
Buffer_.pop_front();
--count_;
not_full_.notify_one();
return w;
}
This is main:
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <thread>
using std::thread;
#include "buf.h"
Buffer B1{20};
void producer(int id){
B1.append(id);
}
void consumer(){
int w = B1.take();
cout<< w <<endl;
}
int main()
{
for(int i=0; i<5; ++i){
thread prod(producer, i);
thread cons(consumer);
prod.join();
cons.join();
}
return 0;
}
I don't understand why if I use push_back() in append, I get all 0 as output, when instead I should get this:
0
1
2
3
4
If I use push_front() the output is correct. Can anyone help me?
In your constructor:
Buffer_(capacity,0)
This does not do what you think it does. If you inspect what's in the Buffer_ immediately after construction you will discover that it's not empty, and the resulting program's behavior becomes easy to explain.
TLDR: the initializes the buffer with a whole bunch of values, which are all 0, which completely messes up the logic in the rest of the code which assumes that the buffer is initially empty.
I am new to threads, I am trying to simulate the critical section race condition problem in this code.
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
using namespace std::chrono;
int x = 20;
void increment()
{
++x;
}
void decrement()
{
--x;
}
int main()
{
thread t1(increment);
thread t2(decrement);
cout << x;
return 0;
}
But, this code terminates with SIGABRT.
terminate called without an active exception
21
Why I am getting SIGABRT in this code?
You must call join for the threads so that they are properly terminated
t1.join();
t2.join();
Let us say, that we use packaged_task for implementing async work in a program.
#include <map>
#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>
#include <iterator>
#include <future>
#include <thread>
#include <chrono>
int main()
{
std::packaged_task<int()> packagedTaskOne([]()
{
using namespace std::chrono_literals;
std::this_thread::sleep_for(4s);
return 4;
});
std::future<int> futureResultOne = packagedTaskOne.get_future();
std::thread tOne(std::move(packagedTaskOne));
futureResultOne.wait();
tOne.join();
std::cout << "done\n";
return 0;
}
I can barely imagine how to implement waiting cursor in C#, because I can use something like while(!Task.Run(async () => await _service.GetValue()).IsCompleted) and output some dots that show loading. I want the same with packaged_task but I do not understand how to fuse it with while loop because I do not get what a condition I should for checking is this thread completed. How to make the same loop in C++ with packaged_task?
If you don't want to use futureResultOne.get(); to avoid blocking, the following is a way to check if your task has finished or not in the main (you can use an independent one of course) thread.
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <condition_variable>
using namespace std::chrono_literals;
std::condition_variable cv;
bool theThreadHasFinished;
std::mutex mut;
int main()
{
std::packaged_task<int()> packagedTaskOne([]{
std::this_thread::sleep_for(4s);
return 4;
});
std::future<int> futureResultOne = packagedTaskOne.get_future();
std::thread tOne([&]{packagedTaskOne();
std::lock_guard lg{mut};
theThreadHasFinished = true;
cv.notify_all();});
tOne.detach();
std::unique_lock<std::mutex> lock{ mut };
cv.wait(lock, [ ](){ return theThreadHasFinished; });
std::cout << "done\n";
return 0;
}
You can use a while loop ad wait_for but this consumes your resources
I have a small solution in visual studio 2012. The solution consists of two projects (Scanner and TestApp), Scanner is a dll and TestApp is a small application using the dll.
I would like a function in the dll to run in a thread and to report its result back via a queue to the TestApp.
To test this I wrote a minimal application, but depending on how I launch the thread I get different results and I would like to understand why.
The Scanner.h file looks like this:
#pragma once
#include <iostream>
#include <string>
#include <stdint.h>
#include <atomic>
#include <future>
#include <thread>
#include "version.h"
#include "threadsafe_queue.h"
#include "capture_data.h"
#include "process_data.h"
#ifdef SCANNER_EXPORTS
#define SCANNER_API __declspec(dllexport)
#else
#define SCANNER_API __declspec(dllimport)
#endif
class Scanner
{
public:
static SCANNER_API void run();
static SCANNER_API void stop();
};
Scanner.cpp:
#include "stdafx.h"
#include "Scanner.h"
std::vector<std::future<int>> my_futures;
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
my_futures.push_back(std::move(t));
}
void Scanner::stop()
{
for(int n=0; n<my_futures.size(); n++) {
auto e = std::move(my_futures.back());
e.get();
my_futures.pop_back();
}
}
The class CaptureData is defined in capture_data.h and capture_data.cpp.
capture_data.h:
#pragma once
#include <atomic>
#include <thread>
#include "iq_data.h"
#include "threadsafe_queue.h"
class CaptureData
{
public:
CaptureData(double freq_start);
void configure();
void get_data();
private:
double m_test;
};
capture_data.cpp
#include "stdafx.h"
#include "capture_data.h"
#include "Scanner.h"
ThreadsafeQueue<int> g_queue_1;
SCANNER_API ThreadsafeQueue<int> g_queue_2;
CaptureData::CaptureData(double test)
: m_test(test) {}
void CaptureData::get_data()
{
cout << "1: " << m_test << std::endl;
Sleep(5000);
cout << "2: " << m_test << std::endl;
g_queue_2.push(3);
cout << "Capture has now pushed data" << std::endl;
}
And finally the TestApp.cpp:
#include "stdafx.h"
#include "tchar.h"
#include <stdint.h>
#include <string>
#include "Scanner.h"
SCANNER_API extern ThreadsafeQueue<int> g_queue_2;
int _tmain(int argc, _TCHAR* argv[])
{
Scanner scanner;
scanner.run();
cout << "TestApp waiting for data..." << std::endl;
int data;
g_queue_2.wait_and_pop(data);
cout << "TestApp got data: " << data << std::endl;
scanner.stop();
return 0;
}
In Scanner.cpp I have tried to launch the thread in two different ways, the first way:
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
Second way is with a reference to the object "capture_data":
auto t = std::async(std::launch::async, &CaptureData::get_data, &capture_data);
The first way seems to work as I intended the application to work and I get the following printouts in my terminal:
TestApp waiting for data...
1: 1234
2: 1234
Capture has now pushed data
TestApp got data: 3
Press any key to continue...
If I use the second way I get:
TestApp waiting for data...
1: 6.95166e-310
2: 6.95166e-310
Capture has now pushed data
TestApp got data: 3
Press any key to continue...
So, what I do not understand is why the variable "m_test" get messed up in the second case.
I would very much appreciate if anyone could shed a light on this.
/M
In the following code:
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
my_futures.push_back(std::move(t));
}
capture_data is a local variable that goes out of scope and gets destroyed when the function returns. If you pass a pointer to that variable into async that pointer becomes a dangling pointer causing undefined behaviour. That does not happen if you pass it by value, as you do in the above snippet.
You are trying to pass a pointer to a stack allocated object. This object is destructed at the end of the Scanner::run() method. Thus, the pointer is now pointing to invalid memory when the async function runs.
The first method works, because the capture_data variable is move constructed when it is passed to the function, therefore it still retains it's structure.
I recommend using lambda functions than passing the raw member function:
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, [capture=std::move(capture_data)]() { capture.get_data(); });
my_futures.emplace_back(t);
}
Even better is to construct the object inside the lambda function:
void Scanner::run()
{
auto t = std::async(std::launch::async, []() {
CaptureData capture_data(1234);
capture_data.get_data();
});
my_futures.emplace_back(t);
}
I'm initialized thread on main function when created namspace multithread_init in order to push set_multihthread class to namespace. Why after declared boost::thread it's not matching function for call boost::thread t(smulti.thread)?
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <iostream>
#ifndef MULTITHREAD_INIT_HPP_
#define MULTITHREAD_INIT_HPP_
namespace multithread_init{
class set_multithread{
private:
//t;
public:
void thread(){
for(int i = 0; i < 5; i++){
wait(1);
std::cout<<" thread i value : "<<i<<std::endl;
}
}
void wait(int seconds)
{
boost::this_thread::sleep(boost::posix_time::seconds(seconds));
}
// void multi_case(){
// t.join();
// boost::thread t(thread);
// }
};
}
#endif /* MULTITHREAD_INIT_HPP_ */
main file follow as below.
int main()
{
/*thread */
multithread_init::set_multithread smulti;
boost::thread t(smulti.thread);
t.join();
}
You can't pass a member function that way. You need to bind it to the object
boost::thread t(boost::bind(&multithread_init::set_multithread::thread, &smulti));