Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute callback function on main thread from std::thread

I have a requirement of executing a callback function on exit of a std::thread and the callback function should be executed on the main thread.

On thread creation I need to detach the thread and cannot block the main loop execution for thread completion.

i tried using std::signal but that does not seem to execute callback function on the main thread

#include <thread>
#include <csignal>
#include <iostream>


std::thread::id main_thread_id;

void func2()
{
    for(int i = 0; i < 10000000; i++)
    {
        // do something
    }
}

void func()
{
    for(int i = 0; i < 10; i++)
    {
        func2();
    }
    std::raise(SIGUSR1);
}

void callback(int signal)
{
    std::cout << "SIGNAL: " << signal << "      THREAD ID:" << 
    std::this_thread::get_id() << std::endl;
    bool b = std::this_thread::get_id() == main_thread_id;
    std::cout << "IS EXECUTED ON MAIN THREAD: " << b << std::endl;
}

int main()
{
    main_thread_id = std::this_thread::get_id();
    std::cout << "MAIN THREAD ID: " << std::this_thread::get_id() << std::endl;
    std::signal(SIGUSR1, callback);
    std::thread t1(func);
    t1.detach();

    for(int i = 0; i < 20; i++)
    {
        func2();
    }

    if(t1.joinable())
        t1.join();
}

The result I get is that the callback function is not executed on main thread. Please suggest a way in which I can create a worker thread and call a callback function on main thread upon exit of the thread.

Thanks for the help

like image 978
Tushar Avatar asked Jul 26 '17 17:07

Tushar


1 Answers

There are a few ways to do this.

First, your main thread could be running a message loop. In which case, you queue up a message with a payload that tells the main thread to run some code (either carry the code to run via a pointer part of the message to the main thread, or put it in some known spot that the main thread checks).

A second approach is to return something like a std::future<std::function<void()>> object, and the main thread checks if the future is ready. When it is ready, it runs the code.

A third approach is to create a concurrent queue that the main thread waits on, and stuff your message (containing code to run) onto that queue.

All of these things require the active cooperation of the main thread. The main thread cannot be preemted and told to run different code without its cooperation.

Which is best depends on features of your program you did not choose to mention in your question. If you are a graphical GUI with a message loop, use the message loop. If you are a streaming processor that paralellizes some work, and you don't need prompt execution, yet eventually will want to block on the parallel work, a future might be best. If you are a message passing channel-type app, a set of queues might be best.

like image 86
Yakk - Adam Nevraumont Avatar answered Sep 30 '22 06:09

Yakk - Adam Nevraumont