Thread safety and std::move - c++

Preface:
When I'm typing out new code, I declare my functions as pass-by-reference-to-const without thinking (out of habit), and sometimes have to go back and change it when I realize it's not what I meant to do.
I'm writing a worker-thread class that runs indefinitely, and is fed strings (from another thread) for processing. When I realized that I had declared the function as pass-by-ref, I went back to change it to pass-by-value, for thread-safety.
But, since I would like to squeeze out as much speed and efficiency as possible, I stopped myself to first explore the options. I wrote a little test routine - and discovered that I'm fuzzy on some key concepts.
To the point: I first wrote the test code below without the commented line:
// std::thread _thread(workthread, move(str)); // Thread safe (contents are moved)
So, ignore that line for now.
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <atomic>
std::atomic<bool> done = false;
void workthread(const std::string &str)
{
std::string &s = const_cast<std::string &>(str);
s = "Work Thread"; // test to see if this changes the main thread's string
}
// This just watches for <enter> on the keyboard in order to quit the program.
void quitmonitor()
{
std::getchar();
done = true;
}
int main(int argc, char **argv)
{
std::thread _monitor(quitmonitor);
std::string str("Main Thread");
std::thread _thread([&]{workthread(std::move(str));}); // Not thread safe (address is copied)
// std::thread _thread(workthread, move(str)); // Thread safe (contents are moved)
const auto minlen(str.length());
const auto maxlen(minlen ? minlen*2 : 15);
bool going_up = true;
while (!done) {
if (going_up)
str.push_back('+');
else
str.pop_back();
if (str.length() == minlen)
going_up = true;
if (str.length() == maxlen)
going_up = false;
std::cout << str << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
_thread.join();
_monitor.join();
}
All main() does is create a string "Main Thread", and moves it to the thread function void workthread(const std::string &). The thread function then changes the lvalue's data and returns. The main continues on to a loop which just prints its local string to console (with some additional eye-candy to make it easy to see things happening on the screen). Here's the output:
So, it didn't work as I had expected. I had thought that the thread instantiation would "move" str to the thread function (emptying its data in the process), and the thread's assignment to the function's string argument would have no affect. But clearly it did, as demonstrated by the output.
This must have something to do with the fact that I constructed _thread with a lambda:
std::thread _thread([&]{workthread(std::move(str));}); // Not thread safe (address is copied)
So then I changed the instantiation to:
std::thread _thread(workthread, move(str)); // Thread safe (contents are moved)
and it worked as expected:
Q1: Why do the two instances, lambda vs bind(I guess?), yield different results?
Q2: Am I actually buying myself anything by declaring this as pass-by-reference?
I should note that the actual program is quite time critical, and is intended to run uninterrupted for years on a dedicated server. I'm trying to make the software as low-overhead as possible, to ensure that it can stay in sync (with an external clock), and not accumulate time errors.

std::thread _thread([&]{workthread(std::move(str));});
When _thread is created, it calls your lambda function, which calls workthread(std::move(str)). Note that std::move doesn't actually do anything; it's just a cast to rvalue reference. You never move from str, you just cast the reference to a std::string& in a roundabout way and assign to it.
This also means that you have a data race on str because you have unsynchronized access between the main thread and _thread.
This code moved from the string, though:
std::thread _thread(workthread, move(str));
If you look at std::thread's constructor (it's (3) on that list), you'll see that it "copies" the arguments to the function call; it calls roughly:
workthread(decay_copy(std::move(str)))
This decay_copy actually does move from the string, as it returns by value:
template <class T>
std::decay_t<T> decay_copy(T&& v) { return std::forward<T>(v); }
This is why you see str as being moved from. However, your program is actually relying on unspecified behavior, as – after moving from a std::string – the string is left in a "valid but unspecified state" (std::string's move constructor and move assignment operator). You can't expect str to be an empty string after it's been moved from.

Related

Why do I get "Segmentation fault (core dumped)" error when trying to implement multithreading in c++?

I have a main file where I plan to initiate the threads for my c++ program, for now, I only want to get one of the threads up and running before moving on to the others, but that is proving to be difficult. The purpose of the threads is for a TCP Server and Client to run at the same time, I have already tested my TCP code and it works, the issue now is running each one in its own thread. The following shows my main.cpp code:
#include <thread>
#include <iostream>
#include <functional>
#include "./hdr/tcpip_server.hpp"
#include "./hdr/tcpip_client.hpp"
using namespace std;
tcpServer *backendServer;
//This is done because the callback function of std::thread tcpip_server_thread complains when I only use 'backendServer->Monitor' as my callback function
void StartThread (void) {backendServer->Monitor();}
int main (void)
{
/*Initiate and start TCP server thread*/
std::thread tcpip_server_thread; // done to define object to be used outside the scope of the if statement below
if (backendServer->Init())
{
std::thread tcpip_server_thread (StartThread);
}
/*Initiate and start data reader thread*/
//std::thread tcpip_client_thread (tcpip_client);
tcpip_server_thread.join();
//tcpip_client_thread.join();
return 0;
}
The backendServer class is as follows:
class tcpServer
{
private:
int listening;
sockaddr_in hint;
sockaddr_in client;
socklen_t clientSize;
int clientSocket;
char host[NI_MAXHOST];
char service[NI_MAXSERV];
char buf[4096];
public:
bool Init ();
void Monitor ();
};
The only error I am getting with this code is the one in the title, and I only get it when the code is executing, no errors are received while compiling the code.
When trying the following:
std::thread tcpip_server_thread (backendServer->Monitor);
I get the following warning:
a pointer to a bound function may only be used to call the function
and
no instance of constructor "std::thread::thread" matches the argument list
Any help would be appreciated as this is my first project implementing threads.
1. Initializing backendServer:
backendServer is a pointer to tcpServer, but it is uninitialized (and does not point to any valid object).
Therefore backendServer->Init(); invokes UB Undefined Behavior, and likely to crash.
If you must use a pointer you must allocate it. Better still use a smart pointer like std::unique_ptr instead.
But in your case I believe the best solution is not to use a pointer at all, and define backendServer as a local variable in main:
int main(void)
{
tcpServer backendServer;
// ...
}
This will require accessing it with backendServer. instead of backendServer->.
2. The thread issue:
At the moment, you have 2 tcpip_server_thread variables.
The 2nd one inside the if is shadowing the 1st one you have before.
When you get out of the if's scope, the 2nd tcpip_server_thread will be destroyed, and a std::thread must be joined before destruction.
Later on you attempt to join the 1st one which has not even started, causing a 2nd problem.
In order to fix it:
Inside the if, do not declare a new variable. Instead use the one you already have:
tcpip_server_thread = std::thread(StartThread);
If you made backendServer a local in main as suggested above, you can use a lambda that captures it by reference:
tcpip_server_thread = std::thread(
[&backendServer]() { backendServer.Monitor();});
//--------------^^^^^^^^^^^^^^---------------------------------
Before you join the thread check that it is joinable. In the current code this will not be the case if you didn't enter the if that started the thread:
if (tcpip_server_thread.joinable())
{
tcpip_server_thread.join();
}
A side note: Why is "using namespace std;" considered bad practice?.
The main issue of your code is an uninitialised (actually: zero-initialised) pointer:
tcpServer *backendServer;
Note that you never assign a value to! This results in (as a global variable) the pointer being initialised to nullptr, which you dereference illegally later on, e.g. at (the first time during the programme run)
if (backendServer->Init())
which most likely caused the crash. A quick and dirty fix might look as:
int main()
{
backendServer = new tcpServer(); // possibly with arguments, depending
// on how your constructor looks like
// the code you have so far
delete backendServer; // avoid memory leak!!!
return 0;
}
You spare all this hassle around manual memory management (-> explicit delete) if you use smart pointers instead, e.g. std::unique_ptr. However unless you possibly want to dynamically exchange the backend server, limit its life-time to anything else than the entire programme run or construct it with arguments that need to be retrieved/calculated within main before (none of appears pretty likely to me in given case) then you most likely are better off with a global object:
tcpServer backendServer; // note the dropped asterisk!
This way the object is created before entering main and correctly destructed after leaving.
As now no pointer any more you now refer to members via . instead of ->, i.e. backendServer.Monitor() for instance.
You actually can construct a std::thread with member function pointers, too. You need, though, to pass the object on which this member function should get called to the thread as well:
std::thread(&tcpServer::Monitor, backendServer);
This works with both functions and objects, the latter are accepted by value, though, thus if you use a global object as recommended above you might rather want to create a pointer:
std::thread(&tcpServer::Monitor, &backendServer);
// ^ (!)
// note: NOT if your variable remains a pointer!!!
This way you can actually spare the global variable entirely and create the object within main and the StartThread (actually you should better have named it RunThread) gets entirely obsolete as well.
Alternatives to are converting Monitor function into an operator() or adding such one as
void tcpServer::operator()()
{
this->Monitor();
}
which makes the object itself callable, thus you could pass it directly to the thread's constructor (std::thread(std::ref(backendServer)); with std::ref preventing the object getting copied) or using a lambda:
std::thread([&]() { backendServer.Monitor(); });
both with the same advantage as providing the member function that you can spare global variable and StartThread function.
Still your code reveals another problem:
if (backendServer->Init())
{
std::thread tcpip_server_thread(StartThread);
}
You create here a second local variable tcpip_server_thread which, as long as it exists, hides the previous one, but which runs out of scope and thus gets destructed again right after the end of the if-body!
Instead you want to assign the newly created thread to the already existing variable, which would look like:
tcpip_server_thread = std::thread(StartThread);
Actually you get nicer code if you move the entire thread-code into the if block:
// no thread code left here any more
if(backendServer->Init())
{
std::thread tcpip_server_thread(StartThread);
// start second thread here, too!
tcpip_server_thread.join();
}
// no thread code left here any more
Finally you should not join a thread that actually has failed to start. You spot this by checking if the thread is joinable
std::thread tcpip_server_thread (StartThread);
if(tcpip_server_thread.joinable())
{
// see above for correct construction!
std::thread tcpip_client_thread(tcpip_client);
if(tcpip_client_thread.joinable())
{
tcpip_server_thread.join();
}
else
{
// you might need some appropriate error handling like
// printing/logging a warning message
// and possibly stop the server thread
}
}
else
{
error handling, see above
}
To fix the code I had to do 2 things, one was to not define the tcpServer variable, backendServer, as a pointer, since I never pointed it toward an actual object of the type tcpServer.
Next, I removed the first tcpip_server_thread variable and made sure that the code that initiates ```tcpip_server_thread`` and the code that joins it is in the same scope. In the future, I will implement the std::move function as explained by #wohlstad.
My working code:
#include <thread>
#include <iostream>
#include <functional>
#include "./hdr/tcpip_server.hpp"
#include "./hdr/tcpip_client.hpp"
using namespace std;
/*All the threads*/
tcpServer backendServer;
void StartThread (void) {backendServer.Monitor();}
int main (void)
{
/*Initiate and start tcp server thread*/
if (backendServer.Init())
{
std::thread tcpip_server_thread (StartThread);
if (tcpip_server_thread.joinable())
{
tcpip_server_thread.join();
}
else
{
cout << "error";
}
}
return 0;
}

Benefits of using std::stop_source and std::stop_token instead of std::atomic<bool> for deferred cancellation?

When I run several std::threads in parallell and need to cancel other threads in a deferred manner if one thread fails I use a std::atomic<bool> flag:
#include <thread>
#include <chrono>
#include <iostream>
void threadFunction(unsigned int id, std::atomic<bool>& terminated) {
srand(id);
while (!terminated) {
int r = rand() % 100;
if (r == 0) {
std::cerr << "Thread " << id << ": an error occured.\n";
terminated = true; // without this line we have to wait for other thread to finish
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main()
{
std::atomic<bool> terminated = false;
std::thread t1(&threadFunction, 1, std::ref(terminated));
std::thread t2(&threadFunction, 2, std::ref(terminated));
t1.join();
t2.join();
std::cerr << "Both threads finished.\n";
int k;
std::cin >> k;
}
However now I am reading about std::stop_sourceand std::stop_token.
I find that I can achieve the same as above by passing both a std::stop_sourceby reference and std::stop_token by value to the thread function?
How would that be superior?
I understand that when using std::jthread the std::stop_token is very convenient if I want to stop threads from outside the threads.
I could then call std::jthread::request_stop() from the main program.
However in the case where I want to stop threads from a thread is it still better?
I managed to achieve the same thing as in my code using std::stop_source:
void threadFunction(std::stop_token stoken, unsigned int id, std::stop_source source) {
srand(id);
while (!stoken.stop_requested()) {
int r = rand() % 100;
if (r == 0) {
std::cerr << "Thread " << id << ": an error occured.\n";
source.request_stop(); // without this line we have to wait for other thread to finish
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main()
{
std::stop_source source;
std::stop_token stoken = source.get_token();
std::thread t1(&threadFunction, stoken, 1, source);
std::thread t2(&threadFunction, stoken, 2, source);
t1.join();
t2.join();
std::cerr << "Both threads finished.\n";
int k;
std::cin >> k;
}
Using std::jthread would have resulted in more compact code:
std::jthread t1(&threadFunction, 1, source);
std::jthread t2(&threadFunction, 2, source);
But that did not seem to work.
It didn't work because std::jthread has a special feature where, if the first parameter of a thread-function is a std::stop_token, it fills that token in by an internal stop_source object.
What you ought to do is only pass a stop_source (by value, not by reference), and extract the token from it within your thread function.
As for why this is better than a reference to an atomic, there are a myriad of reasons. The first being that stop_source is a lot safer than a bare reference to an object whose lifetime is not under the local control of the thread function. The second being that you don't have to do std::ref gymnastics to pass parameters. This can be a source of bugs since you might accidentally forget to do that in some place.
The standard stop_token mechanism has features beyond just requesting and responding to a stop. Since the response to a stop happens at an arbitrary time after issuing it, it may be necessary to execute some code when the stop is actually requested rather than when it is responded to. The stop_callback mechanism allows you to register a callback with a stop_token. This callback will be called in the thread of the stop_source::request_stop call (unless you register the callback after the stop was requested, in which case it's called right when you register it). This can be useful in limited cases, and it's not simple code to write yourself. Especially when all you have is an atomic<bool>.
And then there's simple readability. Passing a stop_source tells you exactly what is going on without having to even see the name of a parameter. Passing an atomic<bool> tells you very little from just the typename; you have to look at the parameter name or its usage in the function to know that it is for halting the thread.
Apart from being more expressive and communicating intentions better, stop_token and friends achieve something really important for jthread. To understand it you have to consider its destructor which looks something like this:
~jthread()
{
if(joinable())
{
// Not only user code, but the destructor as well
// will let your callback know it's time to go.
request_stop();
join();
}
}
by encapsulating a stop_source, jthread facilitates what is called cooperative cancellation. As you've also noted, you never have to pass the stop_token to a jthread, just provide a callback that accepts the token as its first parameter. What happens next is that the class can detect that your callback accepts a stop token and pass a token to its internal stop source when calling it.
What does this mean for cooperative cancellation? Safer termination of course! Since jthread will always attempt to join on destruction, it now has the means to prevent endless loops and deadlocks where two or more threads wait for each other to finish. By using stop_token your code can make sure that it can safely join when it's time to go.
However in the case where I want to stop threads from a thread is it still better?
Now regarding the feature you are requesting, that's what C# calls "linked cancellation". Yes, there are requests and discussions to add a parameter in the jthread constructor so that it can refer to an external stop source, but that's not yet available (and has many implications). Doing something similar purely with stop tokens would require a stop_callback to tie all cancellations together, but still it could be suboptimal (as shown in the link). The bottom line is that jthread needs stop_token, but in some cases you may not need jthread, especially if the following solution does not appeal to you:
stop_source ssource;
std::stop_callback cb {ssource.get_token(), [&] {
t1.request_stop();
t2.request_stop();
}};
ssource.request_stop(); // This stops boths threads.
The good news is that if you don't fall into the suboptimal pattern described in the link (i.e. you don't need an asynchronous termination), then this functionality is easy to abstract into a utility, something like:
auto linked_cancellations = [](auto&... jthreads) {
stop_source s;
return std::make_pair(s, std::stop_callback{
s.get_token(), [&]{ (jthreads.request_stop(), ...); }});
};
which you'd use as
auto [stop_source, cb] = linked_cancellations(t1, t2);
// or as many thread objects as you want to link ^^^
stop_source.request_stop(); // Stops all the threads that you linked.
Now if you want to control the linked threads from within the thread, I'd use the initial pattern (std::atomic<bool>), since having a callback with both a stop token and a stop source is somewhat confusing.

C++ Errors C2893, C2780, C2672 when using future, promise, detached thread

I have got a class named cApp.
I want to run CheckProcessList() in the background until the program terminates. So i thought, well, lets run it in a detached thread until ~cApp(). I made a bool to break out of the loop in CheckProcessList(). In ~cApp I set the bool true m_bTerminateThread = true to break out and wait for the promise m_barrierFuture->wait() that the thread has ended execution. After breaking out i set the promise barrier.set_value() that the thread is now ending execution. Now ~cApp can finish execution. Or at least that is my understanding of the things i want to achieve and how to do it. Well, can't be right since i get Compiler Errors.
Why did it want to check if the thread finished in the first place? Because the program breaks at runtime when it terminates and the thread is at that moment in GetProcId(). If it is sleeping in the moment of termination the program does not break.
I searched msdn and stackoverflow for answers but i do not get anything out of it that i can understand. I am using VS2019 and C++14. Thank you guys in advance.
cApp.h
#pragma once
#include "wx/wx.h"
#include "cMain.h"
#include <thread>
#include <future>
class cApp
: public wxApp
{
public:
cApp();
~cApp();
virtual bool OnInit();
private:
// supposed to run in a detached thread
// until the program terminates
void CheckProcessList(std::promise<void> barrier);
// Checks whether or not the game processes are running
// this thread runs asynchronous until ~cApp
std::thread* m_tCheckProcList;
// used in thread "m_tCheckProcList"
// if set to true the thread terminates asap
bool m_bTerminateThread;
// used in thread "m_tCheckProcList"
// in ~cApp this future waits for the promise that the thread has finished
std::future<void>* m_barrierFuture;
// Dark Souls 3 Processname
const wchar_t* m_ds3Name;
// Need for Speed: Most Wanted Processname
const wchar_t* m_nfsmwName;
// Serious Sam: The Second Encounter Processname
const wchar_t* m_sstseName;
const wxString* m_frameTitle;
const wxSize* m_frameSize;
cMain* m_mainFrame;
};
cApp.cpp
#include "cApp.h"
wxIMPLEMENT_APP(cApp);
cApp::cApp()
{
m_ds3Name = L"DarkSoulsIII.exe";
m_sstseName = L"SeriousSam.exe";
m_nfsmwName = L"speed.exe";
m_frameTitle = new wxString("DeltaWin");
m_frameSize = new wxSize(600, 450);
m_bTerminateThread = false;
m_mainFrame = nullptr;
m_tCheckProcList = nullptr;
m_barrierFuture = nullptr;
}
cApp::~cApp()
{
// send the thread the "signal" to finish asap
m_bTerminateThread = true;
// wait for thread "m_tCheckProcList" to finish execution
m_barrierFuture->wait();
}
bool cApp::OnInit()
{
// create main top-level window
m_mainFrame = new cMain(*m_frameTitle, wxDefaultPosition, *m_frameSize);
m_mainFrame->Show();
// create barrier and instantiate the future for it
std::promise<void> barrier;
m_barrierFuture = new std::future<void>(barrier.get_future());
// start checking for running game processes in asynchronous thread
m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
m_tCheckProcList->detach();
return true;
}
void cApp::CheckProcessList(std::promise<void> barrier)
{
while (!m_bTerminateThread)
{
// Dark Souls 3
if (GetProcId(m_ds3Name) == 0)
m_mainFrame->MenuItemEnable(false, menuItem::DarkSouls3);
else
m_mainFrame->MenuItemEnable(true, menuItem::DarkSouls3);
// Need for Speed: Most Wanted
if (GetProcId(m_nfsmwName) == 0)
m_mainFrame->MenuItemEnable(false, menuItem::NFSMostWanted);
else
m_mainFrame->MenuItemEnable(true, menuItem::NFSMostWanted);
// Serious Sam: The Second Encounter
if (GetProcId(m_sstseName) == 0)
m_mainFrame->MenuItemEnable(false, menuItem::SeriousSamTSE);
else
m_mainFrame->MenuItemEnable(true, menuItem::SeriousSamTSE);
// Sleep 1.5s to save resources
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
}
// set the promise that the thread has ended execution
barrier.set_value();
}
edit:
The program terminates after ~cApp. Therefor i think that in this particular case i do not have to delete all of that memory because the os takes care of it.
edit2:
C2893: Failed to specialize function template
"unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...)
noexcept()".
C2780: "unknown-type std::invoke(_Callable &&) noexcept()":
expects 1 arguments - 2 provided
C2672: "invoke": no matching overloaded function found
m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
I don't know to which lines your errors pertains (you didn't show this) but I suspect at least above statement is wrong.
If you pass an address of a thread procedure to std::thread constructor and this procedure is a non-static member function the next argument after must be an address of the object you refer to (after all a non-static member function must have an instance that it is called on behalf of). std::promise is not a type which contains such a function pointer type &cApp::CheckProcessList so this cannot work.
If you want to associate that thread with the object that creates it typically such invocation looks like:
std::thread(&cApp::CheckProcessList, this, ...
Or one can use either a static member function or a free function.
cApp::CheckProcessList(std::promise<void> barrier)
Another problem in your code is passing a promise object by value to the thread function. This means a local copy of the promise but promise is not copyable.
You also can't pass it either by reference or by pointer! because barrier is a local variable of OnInit() method and as soon as that method finishes that variable gets destroyed anyway - the underlying detached thread will mess around with invalid stackframe or cause undefined behavior of any kind. Perhaps you could make the barrier a data member or rethink your design.
Be very cautious while dealing with detached threads. They are full of pitfalls when used improperly.

How to give the user some assigned time to answer?

Something like a stopwatch, give the person who is using my program about 30 second to answer, if no answer is got the program to exit ?
Basically the response shouldn't take more than the time given, otherwise the program will exit.
I found the answer by Axalo interesting, however fatally flawed by unfortunate minutia of std::async and std::future. So I'm presenting an alternative that eschews std::async but otherwise follows Axalo's basic design.
When I run Axalo's answer on my platform (which is conforming in the pertinent details), if the client never answers, getInputWithin never returns or exits. The program just hangs. And if the client answers well within the timeout, getInputWithin returns with the correct answer, but doesn't do so until the timeout period has expired.
The reason for this problem is subtle. It is well described in Herb Sutter's excellent paper N3630. A ~std::future() can block if it was returned by std::async() and will block until the associated task is done. This feature was intentionally put into async/future, and in the eyes of some, makes future completely useless.
Axalo's r1 and r2 are such std::futures whose destructor is supposed to block until the associated task is done. And this is why this solution hangs if the client never answers.
Below is an alternative answer which is built from thread, mutex, and condition_variable. It is otherwise very similar to Axalo's answer, but does not suffer from (what some consider) the design flaws of std::async.
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
#include <thread>
#include <tuple>
std::string
getInputWithin(std::chrono::seconds timeout)
{
auto sp = std::make_shared<std::tuple<std::mutex, std::condition_variable,
std::string, bool>>();
std::thread([sp]() mutable
{
std::getline(std::cin, std::get<2>(*sp));
std::lock_guard<std::mutex> lk(std::get<0>(*sp));
std::get<3>(*sp) = true;
std::get<1>(*sp).notify_one();
sp.reset();
}).detach();
std::unique_lock<std::mutex> lk(std::get<0>(*sp));
if (!std::get<1>(*sp).wait_for(lk, timeout, [&]() {return std::get<3>(*sp);}))
throw std::runtime_error("time out");
return std::get<2>(*sp);
}
int main()
{
std::cout << "please answer within 10 seconds...\n";
std::string answer = getInputWithin(std::chrono::seconds(10));
std::cout << answer << '\n';
}
Notes:
The timing stays within the chrono type system always. Prefer the type std::chrono::seconds to a scalar with a suggestive name (int timeoutInSeconds vs std::chrono::seconds timeout).
We need to launch a std::thread to handle the read from std::cin, as Axalo demonstrated. However we are going to need a std::mutex and std::condition_variable for communication instead of using the convenience of std::future. Both the main thread and this auxiliary thread need to share ownership of these communication objects, and we don't know which will die first. If the client never responds, the auxiliary thread may live forever, creating an effective memory leak, which is another problem not solved herein. But at any rate, the easiest way to share ownership is to store the communication objects with a copied std::shared_ptr. Last one out turns out the lights.
Launch a std::thread that waits for std::cin and signals the main thread if it gets it. The signaling must be done with the mutex locked. Note that this thread can be (indeed must be) detached. The thread can not touch any memory that it does not own (because of the shared_ptr owning all referenced memory). If main exits while the auxiliary thread is running, the OS will bring the thread down gracefully with no UB.
The main thread then locks the mutex and does a wait_for on the condition_variable using the specified timeout, and a predicate that is checking for the bool in the tuple to turn to true. This wait_for will either return early with that bool set to true, or it will return with it set to false after timeout seconds. If they race (timeout and client answer at the same time) it is ok, either there will be a string there or not, and the bool in the tuple answers that question. While
the main thread is executing the wait_for, the mutex is unlocked so the auxiliary thread can use it.
If the main thread returns and the bool in the tuple has not been set to true, then an exception is thrown. If this exception is not caught, std::terminate() will be called. Otherwise, the string in the tuple will have the client's response.
This approach is susceptible to a client creating many responses to which it never answers, and thus effectively growing memory leaks held by shared_ptrs which never get destructed. Solving that problem is not something I know how to do in portable C++.
In C++14, a slight modification can be done with getInputWithin which reduces the error of choosing the wrong member of the tuple. Since our tuple is composed of all different types, we can index it by type instead of by position:
std::string
getInputWithin(std::chrono::seconds timeout)
{
auto sp = std::make_shared<std::tuple<std::mutex, std::condition_variable,
std::string, bool>>();
std::thread([sp]() mutable
{
std::getline(std::cin, std::get<std::string>(*sp)); // here
std::lock_guard<std::mutex> lk(std::get<std::mutex>(*sp)); // here
std::get<bool>(*sp) = true; // here
std::get<std::condition_variable>(*sp).notify_one(); // here
sp.reset();
}).detach();
std::unique_lock<std::mutex> lk(std::get<std::mutex>(*sp)); // here
if (!std::get<std::condition_variable>(*sp).wait_for(lk, timeout,
[&]() {return std::get<bool>(*sp);})) // here
throw std::runtime_error("time out");
return std::get<std::string>(*sp); // here
}
That is, the lines marked // here have been changed with std::get<type>(*sp) as opposed to std::get<index>(*sp).
Update
In a fit of paranoia inspired by the good comment from TemplateRex below, I've added a call to sp.reset() as the last thing the aux thread does. This forces the main thread to be the one to destruct the tuple, eliminating the possibility that the aux thread could stall before destructing its local copy of sp, and let main blow through the atexit chain, and then have the aux thread wake up and run the tuple destructor.
There may be other reasons that exist to make the call to sp.reset() unnecessary. But by adding this preventative medicine, we don't have to worry about it.
If you don't want to use exit and kill the process you could do it this way:
std::string getInputWithin(int timeoutInSeconds, bool *noInput = nullptr)
{
std::string answer;
bool exceeded = false;
bool gotInput = false;
auto r1 = std::async([&answer, &gotInput]()
{
std::getline(std::cin, answer);
gotInput = true;
});
auto r2 = std::async([&timeoutInSeconds, &exceeded]()
{
std::this_thread::sleep_for(std::chrono::seconds(timeoutInSeconds));
exceeded = true;
});
while(!gotInput && !exceeded)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
if(gotInput)
{
if(noInput != nullptr) *noInput = false;
return answer;
}
if(noInput != nullptr) *noInput = true;
return "";
}
int main()
{
std::cout << "please answer within 10 seconds...\n";
bool noInput;
std::string answer = getInputWithin(10, &noInput);
return 0;
}
The nice thing about this is that you can now handle the missing input by using a default value or simply give the user a second chance, etc...

Error about std::promise in C++

I am trying to pass my class instance into threads and the return the processed objects from threads. I've googled about C++ multithreading, and found that std::promising can be helpful.
However, I am stuck at the very beginning. Here is my code:
void callerFunc()
{
//...
std::promise<DataWareHouse> data_chunks;
// DataWareHouse is my customized class
//data_chunks has a vector<vector<double>> member variable
std::thread(&run_thread,data_chunks);
// ............
}
void run_thread(std::promise<DataWareHouse> data_chunks)
{
// ...
vector<vector<double>> results;
// ...
data_chunks.set_value(results);
}
The above code generates an error:
`error C2248: 'std::promise<_Ty>::promise' : cannot access private member declared in class 'std::promise<_Ty>'`
May I know what am I wrong and how to fix it?
Many thanks. :-)
Your first problem is that you are using std::thread -- std::thread is a low level class which you should build higher abstractions up on. Threading is newly standardized in C++ in C++11, and all of the rough parts are not filed off yet.
There are three different patterns for using threading in C++11 that might be useful to you.
First, std::async. Second, std::thread mixed with std::packaged_task. And third, dealing with std::thread and std::promise in the raw.
I'll illustrate the third, which is the lowest level and most dangerous, because that is what you asked for. I would advise looking at the first two options.
#include <future>
#include <vector>
#include <iostream>
typedef std::vector<double> DataWareHouse;
void run_thread(std::promise<DataWareHouse> data_chunks)
{
DataWareHouse results;
results.push_back( 3.14159 );
data_chunks.set_value(results);
}
std::future<DataWareHouse> do_async_work()
{
std::promise<DataWareHouse> data_chunks;
std::future<DataWareHouse> retval = data_chunks.get_future();
// DataWareHouse is my customized class
//data_chunks has a vector<vector<double>> member variable
std::thread t = std::thread(&run_thread,std::move(data_chunks));
t.detach(); // do this or seg fault
return retval;
}
int main() {
std::future<DataWareHouse> result = do_async_work();
DataWareHouse vec = result.get(); // block and get the data
for (double d: vec) {
std::cout << d << "\n";
}
}
Live example
With std::async, you'd have a function returning DataWareHouse, and it would return a std::future<DataWareHouse> directly.
With std::packaged_task<>, it would take your run_thread and turn it into a packaged_task that can be executed, and a std::future extracted from it.
std::promise<> is not copyable, and in calling run_thread() you are implicitly trying to invoke the copy constructor. The error message is telling you that you cannot use the copy constructor since it is marked private.
You need to pass a promise by reference (std::promise<DataWareHouse> &). This is safe if callerFunc() is guaranteed not to return until run_thread() is finished with the object (otherwise you will be using a reference to a destroyed stack-allocated object, and I don't have to explain why that's bad).
You're trying to pass the promise to the thread by value; but you need to pass by reference to get the results back to the caller's promise. std::promise is uncopyable, to prevent this mistake.
std::thread(&run_thread,std::ref(data_chunks));
^^^^^^^^
void run_thread(std::promise<DataWareHouse> & data_chunks)
^
The error is telling you you cannot copy an std::promise, which you do here:
void run_thread(std::promise<DataWareHouse> data_chunks)
and here:
std::thread(&run_thread,data_chunks); // makes copy of data_chunks
You should pass a reference:
void run_thread(std::promise<DataWareHouse>& data_chunks);
// ^
And then pass an std::reference_wrapper to the thread, otherwise it too will attempt to copy the promise. This is easily done with std::ref:
std::thread(&run_thread, std::ref(data_chunks));
// ^^^^^^^^
Obviously data_chunks must be alive until the thread finished running, so you will have to join the thread in callerFunc().