等待回调完成的最佳方式

时间:2014-12-26 04:50:26

标签: c++ multithreading synchronization

在下面的代码中,main()函数调用request()函数,该函数调用th_request_async()函数,其中mm_th_done_cb()。

只有在执行mm_th_done_cb()之后,才能在main中继续进行最佳和最有效的方法。

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.
}

3 个答案:

答案 0 :(得分:16)

您可以使用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;
}

如果您不需要从回调中返回任何值,则可以使用std::promise<void>std::future<void>对。

吴强的答案中的两个例子都是错误的。

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;
}

答案 1 :(得分:2)

如果C ++ 11可用,你可以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();
}

或者您可以使用同步机制。例如condition_variable,这是跨平台的。

#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;
}

答案 2 :(得分:0)