Best way for waiting for callback to finish - c++

In the code below, main() function is calling request() function which inter call th_request_async() function which mm_th_done_cb().
What will be the best and efficient way to proceed in main only after the mm_th_done_cb() is executed.
DUMMY CODE
int mm_th_done_cb(int error_code, th_result_s* th_result, void* user_data)
{
return 0;
}
void request()
{
th_request_s MyItemInfo;
strncpy(MyItemInfo.origin_path, szUrl, 1024+1);
MyItemInfo.orientation = 0;
MyItemInfo.func = mm_th_done_cb;
MyItemInfo.used_cache = 1;
th_request_async(MyItemInfo);
}
int main()
{
request();
// Here I need to do something only after mm_th_done_cb() has been excuted.
}

You can use std::promise:
std::promise<int> promise;
int mm_th_done_cb(int error_code, th_result_s* th_result, void* user_data)
{
promise.set_value(error_code /*this value will be returned by the future.get()*/);
return 0;
}
int main()
{
std::future<int> future = promise.get_future();
request();
int value = future.get();
return 0;
}
If you don't need to return any value from the callback, then you can use a std::promise<void> and std::future<void> pair.
Both examples in wuqiang's answer are wrong.
1.
#include <future>
int main()
{
request();
// WRONG: Here we don't want to call 'mm_th_done_cb' ourselves.
std::future<int> myFuture = std::async(mm_th_done_cb);
//wait until mm_th_done_cb has been excuted;
int result = myFuture.get();
}
2.
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
int mm_th_done_cb(int error_code, th_result_s* th_result, void* user_data)
{
cv.notify_one();
return 0;
}
int main()
{
request();
// WRONG: If the 'request' finishes quickly, then the 'mm_th_done_cb'
// callback will be called and will notify the condition variable before
// the following lines execute, i.e. before the main thread starts
// waiting on the condition variable. Thus the 'cv.wait(lck)' will
// never return.
unique_lock<std::mutex> lck(mtx);
cv.wait(lck);
return 0;
}

If C++11 is available,you can std::future
#include <future>
int main()
{
request();
std::future<int> myFuture = std::async(mm_th_done_cb);
//wait until mm_th_done_cb has been excuted;
int result = myFuture.get();
}
or you can use synchronization mechanism.such as condition_variable,which is cross-platform.
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
int mm_th_done_cb(int error_code, th_result_s* th_result, void* user_data)
{
cv.notify_one();
return 0;
}
int main()
{
request();
unique_lock<std::mutex> lck(mtx);
cv.wait(lck);
return 0;
}

You can use RegisterWaitForSingleObject

Related

How to return value from std::thread

I have function that returns me a value. I want to use threads for doSth function and set returning value for variables above, here is an example:
#include <string>
#include <iostream>
#include <thread>
using namespace std;
// func for execution
int doSth(int number)
{
return number;
}
int main()
{
// some code ...
int numberOne; // no value now, but in thread I want to set a value from it
int numberTwo; // depending on function input value
thread t1(doSth, 1); // set numberOne = 1;
thread t2(doSth, 2); // set numberTwo = 2;
// wait them to execute
t1.join();
t2.join();
// now I should have numberOne = 1; numberTwo = 2
// some code ...
return 0;
}
How could I do it?
How to return value from std::thread
Besides std::async shown in other answers, you can use std::packaged_task:
std::packaged_task<int(int)> task{doSth};
std::future<int> result = task.get_future();
task(1);
int numberOne = result.get();
This allows separating creation of the task, and executing it in case that is needed.
Method 1: Using std::async (higher-level wrapper for threads and futures):
#include <thread>
#include <future>
#include <iostream>
int func() { return 1; }
int main(){
std::future<int> ret = std::async(&func);
int i = ret.get();
std::cout<<"I: "<<i<<std::endl;
return 0;
}
Method 2: Using threads and futures:
#include <thread>
#include <future>
#include <iostream>
void func(std::promise<int> && p) {
p.set_value(1);
}
int main(){
std::promise<int> p;
auto f = p.get_future();
std::thread t(&func, std::move(p));
t.join();
int i = f.get();
std::cout<<"I: "<<i<<std::endl;
return 0;
}
My prefered method is encapsulate the call in a specific method returning nothing (and managing error in the same way).
void try_doSth(int number, int* return_value, int* status)
{
try
{
*return_value = doSth(number);
*status = 0;
}
catch(const std::exception& e) { *status = 1; }
catch(...) { *status = 2; }
}
int r1,r2,s1,s2;
std::thread t1(try_doSth, 1, &r1, &s1);
std::thread t2(try_doSth, 2, &r2, &s2);

Spawn thread and do something else while it's running for as long as it's active

I have a simple program below where some long running process someFn works, sets a state, works sets a state, works and sets a state.
While someFn is running, I want the main thread to query the state it's setting for the lifetime of someFn.
Obviously this code is incorrect because T is joinable until it actually joins and this program does not halt.
How do I correctly get the main thread to loop for the lifetime of T and stop looping as soon as T has terminated?
#include <iostream>
#include <thread>
#include <chrono>
int STATE = 0;
static std::mutex mtx;
void setState(int newState) {
std::lock_guard<std::mutex> lg(mtx);
STATE = newState;
}
int getState() {
std::lock_guard<std::mutex> lg(mtx);
return STATE;
}
void someFn() {
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(0);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(1);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(2);
}
int main()
{
std::thread T(someFn);
while (T.joinable()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << getState() << std::endl;
}
T.join();
return 0;
}
Thanks!
Just with std::thread you can't.
But you can easily craft your own signal. For example:
#include <atomic>
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
int STATE = 0;
static std::mutex mtx;
void setState(int newState) {
std::lock_guard<std::mutex> lg(mtx);
STATE = newState;
}
int getState() {
std::lock_guard<std::mutex> lg(mtx);
return STATE;
}
void someFn(std::atomic<bool>& isDone) {
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(0);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(1);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(2);
isDone.store(true);
}
int main() {
std::atomic<bool> isDone{false};
std::thread T(someFn, std::ref(isDone));
while(!isDone.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << getState() << std::endl;
}
T.join();
return 0;
}
You don't need a mutex or other synchronization for std::atomic because it is already thread safe.

How to none blocked join to std thread

I want to keep my code clean and do the things right, to any std::thread I need to do join or detach, but how can I wait (at the main thread) for another thread without blocking the execution of the main thread?
void do_computation()
{
// Calculate 1000 digits of Pi.
}
int main()
{
std::thread td1(&do_computation);
while (running)
{
// Check if thread td1 finish and if yes print a message
// Here are some stuff of the main to do...
// Print to UI, update timer etc..
}
// If the thread has not finished yet here, just kill it.
}
The answer is semaphores. You can use a binary semaphore to synchronize your threads.
You may use System V semaphores or pthread mutexes, but they are somehow legacy in C++. Using Tsuneo Yoshioka's answer, we could implement a C++ way of semaphore, though.
#include <mutex>
#include <condition_variable>
class Semaphore {
public:
Semaphore (int count_ = 0)
: count(count_) {}
inline void notify()
{
std::unique_lock<std::mutex> lock(mtx);
count++;
cv.notify_one();
}
inline void wait()
{
std::unique_lock<std::mutex> lock(mtx);
while(count == 0){
cv.wait(lock);
}
count--;
}
private:
std::mutex mtx;
std::condition_variable cv;
int count;
};
Your implementation may make use of the Semaphore class, like so.
void do_computation()
{
//calculate 1000 digits of Pi.
semaphore.notify();
}
int main()
{
Semaphore semaphore(0);
std::thread td1(&do_computation);
semaphore.wait();
}
You can use std::promise and std::future. More info here and here.
#include <vector>
#include <thread>
#include <future>
#include <numeric>
#include <iostream>
#include <chrono>
void accumulate(std::vector<int>::iterator first,
std::vector<int>::iterator last,
std::promise<int> accumulate_promise)
{
int sum = std::accumulate(first, last, 0);
accumulate_promise.set_value(sum); // Notify future
}
void do_work(std::promise<void> barrier)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
barrier.set_value();
}
int main()
{
// Demonstrate using promise<int> to transmit a result between threads.
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 };
std::promise<int> accumulate_promise;
std::future<int> accumulate_future = accumulate_promise.get_future();
std::thread work_thread(accumulate, numbers.begin(), numbers.end(),
std::move(accumulate_promise));
accumulate_future.wait(); // wait for result
std::cout << "result=" << accumulate_future.get() << '\n';
work_thread.join(); // wait for thread completion
// Demonstrate using promise<void> to signal state between threads.
std::promise<void> barrier;
std::future<void> barrier_future = barrier.get_future();
std::thread new_work_thread(do_work, std::move(barrier));
barrier_future.wait();
new_work_thread.join();
}

this_thread::sleep_for affecting other thread

I have a simple program with two threads, one that pushes a packaged_task into a deque, and other that executes it. In the tasks there is a this_thread::sleep_for, and I would expect that only the "process" thread would wait for it, but both are waiting, making the execution sequential. What I'm missing?
#include <future>
#include <iostream>
#include <deque>
std::mutex m;
std::condition_variable cv;
std::deque<std::packaged_task<void(int)>> deque;
void post() {
int id = 0;
auto lambda = [](int id) {
std::this_thread::sleep_for(std::chrono::seconds(std::rand() % 10 + 1));
std::cout << id << std::endl;
};
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::packaged_task<void(int)> task(lambda);
task(id++);
std::lock_guard<std::mutex> lg(m);
deque.emplace_back(std::move(task));
cv.notify_one();
}
}
void process() {
std::deque<std::packaged_task<void(int)>> to_exec;
while (true) {
while (!to_exec.empty()){
std::future<void> fut = to_exec.front().get_future();
fut.get();
to_exec.pop_front();
}
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []() {return !deque.empty(); });
while (!deque.empty()) {
to_exec.push_back(std::move(deque.front()));
deque.pop_front();
}
}
}
int main() {
std::thread tpost(post);
std::thread tprocess(process);
tpost.join();
tprocess.join();
}
I think more effective will be use std::async instead a sleeping random seconds...

C++11 Watchdog class, test application doesn't want to exit

I am using an online C++11 compiler, link found here: cpp.sh (C++ Shell).
In my current project, I would like to have a watchdog class, to be able to check somehow the status of a thread or FSM (for example).
After some work (I'm not a C++11 guru), I finally got the code below, that compiles ok.
I also did some basic/trivial tests, but it seems the test program doesn't want to exit.
It says "Program running" and the only way to (force) exit is to hit the "Stop" button... :(
Well, my question : What am I doing wrong?
Any ideas, suggestions you can provide are highly appreciated.
Here is the full code, including my test app:
Watchdog (as MCVE):
#include <thread>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <iostream>
using namespace std::chrono;
class Watchdog
{
public:
Watchdog();
~Watchdog();
void Start(unsigned int milliseconds, std::function<void()> callback = 0);
void Stop();
void Pet();
private:
unsigned int m_interval;
std::atomic<bool> m_running;
std::thread m_thread;
std::function<void()> m_callback;
std::mutex m_mutex;
steady_clock::time_point m_lastPetTime;
std::condition_variable m_stopCondition;
void Loop();
};
Watchdog::Watchdog()
{
m_running = false;
}
Watchdog::~Watchdog()
{
Stop();
}
void Watchdog::Start(unsigned int milliseconds, std::function<void()> callback)
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == false)
{
m_lastPetTime = steady_clock::now();
m_interval = milliseconds;
m_callback = callback;
m_running = true;
m_thread = std::thread(&Watchdog::Loop, this);
}
}
void Watchdog::Stop()
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == true)
{
m_running = false;
m_stopCondition.notify_all();
m_thread.join();
}
}
void Watchdog::Pet()
{
std::unique_lock<std::mutex> locker(m_mutex);
m_lastPetTime = steady_clock::now();
m_stopCondition.notify_all();
}
void Watchdog::Loop()
{
std::unique_lock<std::mutex> locker(m_mutex);
while(m_running == true)
{
if(m_stopCondition.wait_for(locker, milliseconds(m_interval)) == std::cv_status::timeout)
{
if(m_callback != nullptr)
m_callback();
}
}
}
int main(int argc, char *argv[])
{
Watchdog wdog;
wdog.Start(3000, [] { std::cout << " WDOG TRIGGERED!!! "; });
for(auto i = 0; i < 10; i++)
{
std::cout << "[+]";
wdog.Pet();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
-
You're doing a deadlock here.
void Watchdog::Stop()
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == true)
{
m_running = false;
m_stopCondition.notify_all();
m_thread.join();
^ ~~~~~~~~~~~~~~
m_mutex is locked; m_thread cannot continue execution
}
}
Some additional suggestion: use simple if conditions, do not compare with true or false.