Modern C++. Return data structure from working thread continuing its execution - c++

I need to launch working thread, perform some initialization, return data structure as initialization result and continue thread execution. What is the best (or possible) code to achieve this using modern c++ features only? Note, launched thread should continue its execution (thread does not terminated as usual). Unfortunately, most solutions assume worker thread termination.
Pseudo code:
// Executes in WorkerThread context
void SomeClass::Worker_treadfun_with_init()
{
// 1. Initialization calls...
// 2. Pass/signal initialization results to caller
// 3. Continue execution of WorkerThread
}
// Executes in CallerThread context
void SomeClass::Caller()
{
// 1. Create WorkerThread with SomeClass::Worker_treadfun_with_init()" thread function
// 2. Sleep thread for some initialization results
// 3. Grab results
// 3. Continue execution of CallerThread
}

I think std::future meets your requirements.
// Executes in WorkerThread context
void SomeClass::Worker_treadfun_with_init(std::promise<Result> &pro)
{
// 1. Initialization calls...
// 2. Pass/signal initialization results to caller
pro.set_value(yourInitResult);
// 3. Continue execution of WorkerThread
}
// Executes in CallerThread context
void SomeClass::Caller()
{
// 1. Create WorkerThread with SomeClass::Worker_treadfun_with_init()" thread function
std::promise<Result> pro;
auto f=pro.get_future();
std::thread([this,&pro](){Worker_treadfun_with_init(pro);}).detach();
auto result=f.get();
// 3. Grab results
// 3. Continue execution of CallerThread
}

Try using a pointer or reference to the data structure with the answer in it, and std::condition_variable to let you know when the answer has been computed:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <vector>
std::vector<double> g_my_answer;
std::mutex g_mtx;
std::condition_variable g_cv;
bool g_ready = false;
void Worker_treadfun_with_init()
{
//Do your initialization here
{
std::unique_lock<std::mutex> lck( g_mtx );
for( double val = 0; val < 10; val += 0.3 )
g_my_answer.push_back( val );
g_ready = true;
lck.unlock();
g_cv.notify_one();
}
//Keep doing your other work..., here we'll just sleep
for( int i = 0; i < 100; ++i )
{
std::this_thread::sleep_for( std::chrono::seconds(1) );
}
}
void Caller()
{
std::unique_lock<std::mutex> lck(g_mtx);
std::thread worker_thread = std::thread( Worker_treadfun_with_init );
//Calling wait will cause current thread to sleep until g_cv.notify_one() is called.
g_cv.wait( lck, [&g_ready](){ return g_ready; } );
//Print out the answer as the worker thread continues doing its work
for( auto val : g_my_answer )
std::cout << val << std::endl;
//Unlock mutex (or better yet have unique_lock go out of scope)
// incase worker thread needs to lock again to finish
lck.unlock();
//...
//Make sure to join the worker thread some time later on.
worker_thread.join();
}
Of course in actual code you wouldnt use global variables, and instead pass them by pointer or reference (or as member variables of SomeClass) to the worker function, but you get the point.

Related

What's the good way to pass data to a thread in c++?

I'm learning multi-thread coding using c++. What I need to do is continuously read word from keyboard, and pass it to a data thread for data processing. I used global variable word[] to pass the data. When word[0] != 0 means a new input from keyboard. And the data thread will set word[0] to 0 once it read the data. It works! But I'm not sure if it safe or not, or there are better ways to do this. Here is my code:
#include <iostream>
#include <thread>
#include <cstdio>
#include <cstring>
using namespace std;
static const int buff_len = 32;
static char* word = new char[buff_len];
static void data_thread () { // thread to handle data
while (1)
{
if (word[0]) { // have a new word
char* w = new char[buff_len];
strcpy(w, word);
cout << "Data processed!\n";
word[0] = 0; // Inform the producer that we consumed the word
}
}
};
static void read_keyboard () {
char * linebuf = new char[buff_len];
thread * worker = new thread( data_thread );
while (1) //enter "end" to terminate the loop
{
if (!std::fgets( linebuf, buff_len, stdin)) // EOF?
return;
linebuf[strcspn(linebuf, "\n")] = '\0'; //remove new line '\n' from the string
word = linebuf; // Pass the word to the worker thread
while (word[0]); // Wait for the worker thread to consume it
}
worker->join(); // Wait for the worker to terminate
}
int main ()
{
read_keyboard();
return 0;
}
The problem with this type of multi threading implementation is busy waiting. The input reader & the data consumer both are busy waiting and wasting the cpu cycles. To overcome this you need Semaphore.
Semaphore s_full(0);
Semaphore s_empty(1);
void data_processor ()
{
while (true) {
// Wait for data availability.
s_full.wait();
// Data is available to you, consume it.
process_data();
// Unblock the data producer.
s_empty.signal();
}
}
void input_reader()
{
while (true) {
// Wait for empty buffer.
s_empty.wait();
// Read data.
read_input_data();
// Unblock data com=nsumer.
s.full.signal();
}
}
In addition this solution will work only for a single data consumer thread. But for multiple data consumer threads you'll need thread safe buffer queue and proper implementation of producer - consumer problem.
See below blog links for additional information to solve this problem:
Thread safe buffer queue:
https://codeistry.wordpress.com/2018/03/08/buffer-queue-handling-in-multithreaded-environment/
Producer - consumer problem:
https://codeistry.wordpress.com/2018/03/09/unordered-producer-consumer/
There are a few problems with your approach:
This method is not scalable. What if you have more than 1 processing thread?
You would need a mutex to synchronise read-write access to the memory stored by word. At the scale of this example, not a big deal. In a "serious" application you might not have the luxury of waiting till you get the data thread stops processing. In that case, you might be tempted to remove the while(word[0]) but that is unsafe.
You fire off a "daemon" thread (not exactly but close enough) to handle your computations. Most of the time the thread is waiting for your input and cannot proceed without it. This is inefficient, and modern C++ gives you a way around it without explicitly handling raw threads using std::async paradigm.
#include <future>
#include <string>
#include <iostream>
static std::string worker(const std::string &input)
{
// assume this is a lengthy operation
return input.substr(1);
}
int main()
{
while (true)
{
std::string input;
std::getline (std::cin, input);
if (input.empty())
break;
std::future<std::string> fut= std::async(std::launch::async, &worker, input);
// Other tasks
// size_t n_stars = count_number_of_stars();
//
std::string result = fut.get(); // wait for the task to complete
printf("Output : %s\n", result.c_str());
}
return 0;
}
Something like this in my opinion is the better approach. std::async will launch a thread (if std::launch::async option is specified) and return a waitable future. The computation will continue in the background, and you can do other work in the main thread. When you need to get the result of your computation, you can get() the result of the future(btw the future can be void too).
Also there are a lot of C-isms in your C++ code. Unless there is a reason to do so, why would you not use std::string?
In modern CPP multithreading, u should be using condition_variable, mutex, and queue to handle this. the mutex prevents mutual reach to the queue and the condition variable makes the reader thread sleep until the writer writes what it write. the following is an example
static void data_thread (std::queue<char> & dataToProcess, std::mutex & mut, std::condition_variable & cv, std::atomic<bool>& finished) { // thread to handle data
std::string readData;
while (!finished)
{
{
std::unique_lock lock{mut};
cv.wait(lock, [&] { return !dataToProcess.empty() || finished; });
if (finished) {
while (!dataToProcess.empty()){
readData += dataToProcess.front();
dataToProcess.pop();
}
}
else{
readData += dataToProcess.front();
dataToProcess.pop();
}
}
std::cout << "\nData processed\n";
}
std::cout << readData;
};
static void read_keyboard () {
std::queue<char> data;
std::condition_variable cv;
std::mutex mut;
std::atomic<bool> finished = false;
std::thread worker = std::thread( data_thread, std::ref(data), std::ref(mut), std::ref(cv), std::ref(finished) );
char temp;
while (true) //enter "end" to terminate the loop
{
if (!std::cin.get(temp)) // EOF?
{
std::cin.clear();
finished = true;
cv.notify_all();
break;
}
{
std::lock_guard lock {mut};
data.push(temp);
}
cv.notify_all();
}
worker.join(); // Wait for the worker to terminate
}
int main ()
{
read_keyboard();
return 0;
}
What you are looking for is a message queue. This needs mutex and condition variable.
Here is one on github (not mine but it popped up when I searched) https://github.com/khuttun/PolyM
and another
https://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
I will get told off for posting links, but I am not going to type the entire code here and github's not going anywhere soon

How to stop the thread execution in C++

I created one thread in my main program, thread execution has to stop once the main program will terminate. I am using reader.join(); to terminate the thread execution. But it is not stopping the execution.
I tried with below-mentioned code, I am using thread.join(); function, but it is failed to terminate a thread. And after the main program also my thread is kept executing.
#include <algorithm>
#include <array>
#include <atomic>
#include <mutex>
#include <queue>
#include <cstdint>
#include <thread>
#include <vector>
using namespace std;
using namespace std::chrono;
typedef pair<int, Mat> pairImage;
class PairComp {
public:
bool operator()(const pairImage& n1, const pairImage& n2) const
{
if (n1.first == n2.first)
return n1.first > n2.first;
return n1.first > n2.first;
}
};
int main(int argc, char* argv[])
{
mutex mtxQueueInput;
queue<pairImage> queueInput;
int total = 0;
atomic<bool> bReading(true);
thread reader([&]() {
int idxInputImage = 0;
while (true) {
Mat img = imread("img_folder/");
mtxQueueInput.lock();
queueInput.push(make_pair(idxInputImage++, img));
if (queueInput.size() >= 100) {
mtxQueueInput.unlock();
cout << "[Warning]input queue size is " << queueInput.size();
// Sleep for a moment
sleep(2);
}
else {
mtxQueueInput.unlock();
}
}
bReading.store(false);
});
while (true) {
pair<int, Mat> pairIndexImage;
mtxQueueInput.lock();
if (queueInput.empty()) {
mtxQueueInput.unlock();
if (bReading.load())
continue;
else
break;
}
else {
// Get an image from input queue
pairIndexImage = queueInput.front();
queueInput.pop();
}
mtxQueueInput.unlock();
cv::Mat frame = pairIndexImage.second;
cv::rectangle(frame, cv::Rect{ 100, 100, 100, 100 }, 0xff);
}
cv::imshow("out_image", frame);
waitKey(1);
if (total++ == 200)
break;
if (reader.joinable()) {
reader.join();
}
return 0;
}
thread.join() does not cause the thread to terminate, it waits until the thread ends. It's the responsibility of the thread to end its execution, for example by periodically checking for a certain condition, like a flag.
You already have an atomic flag bReading, which appears to cause the thread to exit.
if (queueInput.empty()) {
mtxQueueInput.unlock();
if (bReading.load())
continue;
else
break; // thread will exit when queue is empty and bReading == false
So all you need is to set bReading = false in the outer thread before calling thread.join().
bReading = false;
reader.join();
Note that bReading.store(false); inside your thread will have no effect.
Note: you don't need to call atomic.load() and atomic.store(), you can just use them in your code, which will call load() and store() implicitly.
I'm not aware of an built in possibility to stop a thread. Since you have a endless-loop embedded in your thread, it won't stop at any time.
std::thread::join does not terminate your thread. You have to implement something to end your loop, when you demand it.
A bool variable you set false when the thread has to exit. e.g. while(run) or something like that; for simplicity you could also use a std::atomic<bool>
A signaling variable you check. std::condition_variable
What you do at the moment is, you wait in your main-thread that your thread terminates. Since std::thread::join does't terminate your thread, your main-thread will execute forever.
NOTE: When you choose to implement the bool solution. You should protect this bool with an mutex or something alike.
Thanks for the comment. As I don't want to point everyone to boost, but you mentioned it. Find information here.
The problem is not with join which (btw) is not meant to be used to stop or terminate a thread.
The function that your thread is executing contains a while(true) which will never terminate, because it can only sleep and unlock the lock, nothing else.
This means that bReading.store will never be called and as a consequence in the main thread loop you will always go though this branch of the is
if (bReading.load())
continue;
meaning that also the main will execute forever.
std::join is used to wait from a thread that another thread has completed its work. when you do thread1.join() from the main thread what happens is that main will wait until thread1 has completed its execution before executing any other instruction.

How can I safely terminate worker threads when they are complete?

I was trying to implement a master-worker model using the C++ 11 synchronization features for practice. The model uses a std::queue object along with a condition variable and some mutexes. The master thread puts tasks in the queue and the worker threads pops a task off the queue and "processes" them.
The code I have works properly (unless I've missed some race conditions) when I don't terminate the worker threads. However, the program never ends until you manually terminate it with Ctrl+C. I have some code to terminate the workers after the master thread finishes. Unfortunately, this doesn't work properly as it skips the last task on some execution runs.
So my question:
Is it possible to safely and properly terminate worker threads after all tasks have been processed?
This was just a proof of concept and I'm new to C++ 11 features so I apologize for my style. I appreciate any constructive criticism.
EDIT: nogard has kindly pointed out that this implementation of the model makes it quite complicated and showed me that what I'm asking for is pointless since a good implementation will not have this problem. Thread pools are the way to go in order to implement this properly. Also, I should be using an std::atomic instead of a normal boolean for worker_done (Thanks Jarod42).
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>
//To sleep
#include <unistd.h>
struct Task
{
int taskID;
};
typedef struct Task task;
//cout mutex
std::mutex printstream_accessor;
//queue related objects
std::queue<task> taskList;
std::mutex queue_accessor;
std::condition_variable cv;
//worker flag
bool worker_done = false;
//It is acceptable to call this on a lock only if you poll - you will get an inaccurate answer otherwise
//Will return true if the queue is empty, false if not
bool task_delegation_eligible()
{
return taskList.empty();
}
//Thread safe cout function
void safe_cout(std::string input)
{
// Apply a stream lock and state the calling thread information then print the input
std::unique_lock<std::mutex> cout_lock(printstream_accessor);
std::cout << "Thread:" << std::this_thread::get_id() << " " << input << std::endl;
}//cout_lock destroyed, therefore printstream_accessor mutex is unlocked
void worker_thread()
{
safe_cout("worker_thread() initialized");
while (!worker_done)
{
task getTask;
{
std::unique_lock<std::mutex> q_lock(queue_accessor);
cv.wait(q_lock,
[]
{ //predicate that will check if available
//using a lambda function to apply the ! operator
if (worker_done)
return true;
return !task_delegation_eligible();
}
);
if (!worker_done)
{
//Remove task from the queue
getTask = taskList.front();
taskList.pop();
}
}
if (!worker_done)
{
//process task
std::string statement = "Processing TaskID:";
std::stringstream convert;
convert << getTask.taskID;
statement += convert.str();
//print task information
safe_cout(statement);
//"process" task
usleep(5000);
}
}
}
/**
* master_thread():
* This thread is responsible for creating task objects and pushing them onto the queue
* After this, it will notify all other threads who are waiting to consume data
*/
void master_thread()
{
safe_cout("master_thread() initialized");
for (int i = 0; i < 10; i++)
{
//Following 2 lines needed if you want to don't want this thread to bombard the queue with tasks before processing of a task can be done
while (!task_delegation_eligible() ) //task_eligible() is true IFF queue is empty
std::this_thread::yield(); //yield execution to other threads (if there are tasks on the queue)
//create a new task
task newTask;
newTask.taskID = (i+1);
//lock the queue then push
{
std::unique_lock<std::mutex> q_lock(queue_accessor);
taskList.push(newTask);
}//unique_lock destroyed here
cv.notify_one();
}
safe_cout("master_thread() complete");
}
int main(void)
{
std::thread MASTER_THREAD(master_thread); //create a thread object named MASTER_THREAD and have it run the function master_thread()
std::thread WORKER_THREAD_1(worker_thread);
std::thread WORKER_THREAD_2(worker_thread);
std::thread WORKER_THREAD_3(worker_thread);
MASTER_THREAD.join();
//wait for the queue tasks to finish
while (!task_delegation_eligible()); //wait if the queue is full
/**
* Following 2 lines
* Terminate worker threads => this doesn't work as expected.
* The model is fine as long as you don't try to stop the worker
* threads like this as it might skip a task, however this program
* will terminate
*/
worker_done = true;
cv.notify_all();
WORKER_THREAD_1.join();
WORKER_THREAD_2.join();
WORKER_THREAD_3.join();
return 0;
}
Thanks a lot
There is visibility issue in your program: the change of worker_done flag made in one thread might not be observed by worker thread. In order to guarantee that the results of one action are observable to a second action, then you have to use some form of synchronization to make sure that the second thread sees what the first thread did.
To fix this issue you can use atomic as proposed by Jarod42.
If you do this program for practicing it's fine, but for the real applications you could profit from existing thread pool, which would greatly simplify your code.

How to use a thread to break a loop in main c++

I am using the following thread in c++ to check if a certain condition is met and if so then it should break the loop. I call the thread in a while loop so I need that to break.
The refresh token is updated by another thread.
void ThreadCheck( void* pParams )
{
if(refresh)
{
continue;
}
}
My while loop:-
while(crun)
{
refresh = false;
_beginthread( ThreadCheck, 0, NULL );
rlutil::setColor(8);
cout<<"Send>> ";
getline(cin, msg); //Make a custom function of this.
if(stricmp(msg.c_str(), "exit")==0)
{
crun = false;
}
else if(msg.empty() || stricmp(msg.c_str()," ")==0)
{
rlutil::setColor(4);
cout<<"Plz enter a valid message!\n";
continue;
} else {
manager('c', msg);
// msg.append("\n");
// chat_out<<msg;
// chat_out.close();
}
cout<<"\n";
}
You cannot modify a value in one thread while another thread is, or might be, accessing it. You need to use some form of synchronization, such as a lock.
You have 2 threads : 1) main, 2) ThreadCheck. Add a mutex so as not to update the 'crun' at the same time and inside the thread update the value to false. That's it
#include <iostream>
#include "/tbb/mutex.h"
#include "/tbb/tbb_thread.h"
using namespace tbb;
typedef mutex myMutex;
static myMutex sm;
int i = 0;
void ThreadCheck( )
{
myMutex::scoped_lock lock;//create a lock
lock.acquire(sm);//Method acquire waits until it can acquire a lock on the mutex
//***only one thread can access the lines from here...***
crun = false;;//update is safe (only one thread can execute the code in this scope) because the mutex locked above protects all lines of code until the lock release.
sleep(1);//simply creating a delay to show that no other thread can update
std::cout<<"ThreadCheck "<<"\n";
//***...to here***
lock.release();//releases the lock (duh!)
}
int main()
{
tbb_thread my_thread(ThreadCheck);//create a thread which executes 'someFunction'
// ... your code
my_thread.join();//This command causes the main thread (which is the 'calling-thread' in this case) to wait until thread1 completes its task.
}

How to correctly exit a std::thread that might be waiting on a std::condition_variable?

I have a class that implements a threaded producer/consumer system using a mutex and two condition variables for synchronization. The producer signals the consumer thread when there are items to use, and the consumer signals the producer thread when it has consumed the items. The threads continue producing and consuming until the destructor requests them to quit by setting a boolean variable. Because either of the threads may be waiting on a condition variable, I have to implement a second check of the quit variable, which feels wrong and messy...
I've reduced the problem down to the following (working on GNU/Linux with g++4.7) example:
// C++11and Boost required.
#include <cstdlib> // std::rand()
#include <cassert>
#include <boost/circular_buffer.hpp>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
// Creates a single producer and single consumer thread.
class prosumer
{
public:
// Create the circular buffer and start the producer and consumer thread.
prosumer()
: quit_{ false }
, buffer_{ circular_buffer_capacity }
, producer_{ &prosumer::producer_func, this }
, consumer_{ &prosumer::consumer_func, this }
{}
// Set the quit flag and wait for the threads to exit.
~prosumer()
{
quit_ = true;
producer_.join();
consumer_.join();
}
private:
// Thread entry point for the producer.
void producer_func()
{
// Value to add to the ringbuffer to simulate data.
int counter = 0;
while ( quit_ == false )
{
// Simulate the production of some data.
std::vector< int > produced_items;
const auto items_to_produce = std::rand() % circular_buffer_capacity;
for ( int i = 0; i < items_to_produce; ++i )
{
produced_items.push_back( ++counter );
}
// Get a lock on the circular buffer.
std::unique_lock< std::mutex > lock( buffer_lock_ );
// Wait for the buffer to be emptied or the quit flag to be set.
buffer_is_empty_.wait( lock, [this]()
{
return buffer_.empty() == true || quit_ != false;
} );
// Check if the thread was requested to quit.
if ( quit_ != false )
{
// Don't let the consumer deadlock.
buffer_has_data_.notify_one();
break;
}
// The buffer is locked by this thread. Put the data into it.
buffer_.insert( std::end( buffer_ ), std::begin( produced_items ), std::end( produced_items ) );
// Notify the consumer that the buffer has some data in it.
buffer_has_data_.notify_one();
}
std::cout << "producer thread quit\n";
}
// Thread entry for the consumer.
void consumer_func()
{
int counter_check = 0;
while ( quit_ == false )
{
std::unique_lock< std::mutex > lock( buffer_lock_ );
// Wait for the buffer to have some data before trying to read from it.
buffer_has_data_.wait( lock, [this]()
{
return buffer_.empty() == false || quit_ != false;
} );
// Check if the thread was requested to quit.
if ( quit_ != false )
{
// Don't let the producer deadlock.
buffer_is_empty_.notify_one();
break;
}
// The buffer is locked by this thread. Simulate consuming the data.
for ( auto i : buffer_ ) assert( i == ++counter_check );
buffer_.clear();
// Notify the producer thread that the buffer is empty.
buffer_is_empty_.notify_one();
}
std::cout << "consumer thread quit\n";
}
// How many items the circular buffer can hold.
static const int circular_buffer_capacity = 64;
// Flag set in the destructor to signal the threads to stop.
std::atomic_bool quit_;
// Circular buffer to hold items and a mutex for synchronization.
std::mutex buffer_lock_;
boost::circular_buffer< int > buffer_;
// Condition variables for the threads to signal each other.
std::condition_variable buffer_has_data_;
std::condition_variable buffer_is_empty_;
std::thread producer_;
std::thread consumer_;
};
int main( int argc, char **argv )
{
(void)argc; (void) argv;
prosumer test;
// Let the prosumer work for a little while.
std::this_thread::sleep_for( std::chrono::seconds( 3 ) );
return EXIT_SUCCESS;
}
If you look at the producer_func and consumer_func thread functions you can see that they loop until the quit variable is set by the prosumer destructor, but they also check for the quit variable again after they lock the circular buffer. If the quit variable was set, they signal each other to prevent a deadlock.
Another idea I had was to call notify_one() on the condition variables from the destructor, would that be a better solution?
Is there a better way to do this?
Update 1: I forgot to mention that in this instance, when the threads are requested to exit, the consumer does not need to consume any remaining data in the circular buffer and it's fine if the producer produces a little bit more too. As long as they both exit and don't deadlock all will be well.
In my opinion, calling notify_one (or rather notify_all if you were to extend your buffer to multiple producers/consumers) on both condition variables in the destructor before the calls to join would be the preferred solution for several reasons:
Firstly, this matches the way that conditional variables are typically used: By setting quit_, you change the state that the producer/consumer threads are interested in and wait for, so you should notify them of the state change.
Furthermore, notify_one should not be a very costly operation.
Also, in a more realistic application, it could be the case that in between the production of two elements, there is a delay; in that case you may not want to block in your destructor until the consumer notices it has to cancel as soon as the next element is enqueued; in the example code, that does not occur, as far as I can see.
In my opinion, there are two functionalities that can be separated:
message passing and dispatching
producing and consuming
It does make sense to really separate them: the 'worker' thread does nothing more than process 'messages' that could mean 'quit' or 'do_work'.
This way you can create a generic 'worker' class that aggregates the actual function. The produce and consume methods stay clean, and the worker class care only about keeping the work going.