Best way for waiting for callback to finish
Asked Answered
G

3

12

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.
}
Georgeannageorgeanne answered 26/12, 2014 at 4:50 Comment(0)
C
5

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;
}
Citarella answered 26/12, 2014 at 7:14 Comment(7)
th_request_async(); function call the mm_th_done_cb function which is passed MyItemInfo.func = mm_th_done_cb; And in the mm_th_done_cb callback function I retrieve the required value for which I have called th_request_async.Georgeannageorgeanne
In my case I have to call 3 similar function to get the value and before that I have to wait. I need advice for dealing such scenarios in best possible way.Georgeannageorgeanne
Main() is calling calling request() can request is calling th_request_async() which is a library function which is calling the registered callback function mm_th_done_cb()Georgeannageorgeanne
Does c++11 have semaphore also?Georgeannageorgeanne
@dearvivekkumar.there is no semaphore in C++11,but you can implement it use mutex and condition variable.ref:#4792949Citarella
can you please explanation how can I implementing this with semaphore of pathread.Georgeannageorgeanne
@mafu is right, this answer is incorrect. Using lock and signals with callbacks is very poor design and leads to unknown behaviors.Shipshape
T
25

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;
}
Transact answered 26/7, 2016 at 18:44 Comment(0)
C
5

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;
}
Citarella answered 26/12, 2014 at 7:14 Comment(7)
th_request_async(); function call the mm_th_done_cb function which is passed MyItemInfo.func = mm_th_done_cb; And in the mm_th_done_cb callback function I retrieve the required value for which I have called th_request_async.Georgeannageorgeanne
In my case I have to call 3 similar function to get the value and before that I have to wait. I need advice for dealing such scenarios in best possible way.Georgeannageorgeanne
Main() is calling calling request() can request is calling th_request_async() which is a library function which is calling the registered callback function mm_th_done_cb()Georgeannageorgeanne
Does c++11 have semaphore also?Georgeannageorgeanne
@dearvivekkumar.there is no semaphore in C++11,but you can implement it use mutex and condition variable.ref:#4792949Citarella
can you please explanation how can I implementing this with semaphore of pathread.Georgeannageorgeanne
@mafu is right, this answer is incorrect. Using lock and signals with callbacks is very poor design and leads to unknown behaviors.Shipshape
F
0

You can use RegisterWaitForSingleObject

Fechter answered 26/12, 2014 at 8:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.