Linux to support multi-threaded application callbacks

I need to create a shared library that provides a set of APIs to be used by multiple processes, which can have more than one thread from which the API is called.

This shared library in turn uses another third party library for which I need to register a callback. The third party library calls the registered callback from another thread.

I want to know how to block a thread when calling APIs defined in my library and release it when I receive a callback from a third party library. This lock should not block another thread from calling the same API ...!

I am using the pthread library to build my library.

Psudo code:

My library:

int lib_init()
{
    register_callback(callback);
}

int lib_deinit()
{
    unregister_callback();
}

int callback(void *)
{
    <unblock the functions>
}

int function1(int, int)
{
    perform_action();
    <should block till I get a callback from 3rd party library>
}

int function2(char, char)
{
    perform_action();
    <should block till I get a callback from 3rd party library>
}

      

Third party library:

int register_callback(callback)
{
    ....
    launch_thread();
    ....
}

int unregister_callback()
{
    ....
    terminate_thread();
    ....
}

int perform_action()
{
    /* queue action */
}

void* thread(void*arg)
{
    /* perform the action & invoke callback */
    invoke_callback();
}

      

Application:

main()
{
    init_lib();
    ....
    create_new_thread();
    ....
    function1(10, 20);
    ....
    function2('c', 'd');
}

another_thread()
{
    function2('a', 'b');
    ....
}

      

The exact problem I cannot solve is that (how) a locking mechanism I need to implement to block calls to functions defined in my library and wait for a callback from a third party library, assuming my library will be used in multiprocessing and multithreaded environment.

+3


source to share


3 answers


Using the simple pthreads interface, you have to use state variables:

int lib_init()
{
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);
    register_callback(callback);
}

int lib_deinit()
{
    unregister_callback();
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
}

int callback(void *p)
{
    pthread_mutex_lock(&mutex);
    result[??] = p;
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
}

int function1(int, int)
{
    result[??] = NULL;
    perform_action();

    pthread_mutex_lock(&mutex);
    while (result[??] == NULL)
        pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex);
}

int function2(char, char)
{
    result[??] = NULL;
    perform_action();


    pthread_mutex_lock(&mutex);
    while (result[??] == NULL)
        pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex);
}

      



pthread_cond_wait()

unlocks the mutex while it waits.

result[??]

is a means of waiting for some method that you have to come up with in order to associate a specific callback call with specific calls function1()

or function2()

that it has to do with.

+1


source


If you can use C ++ 11 you might be interested in std :: condition_variable and friends. You have to create a condition variable in your function API, pass it to your callback, register the callback with a third party library, and make the API function on it. Then you can unlock it at the end of your callback.

pseudocode:



void your_API_f()
{
    define std::condition_variable;
    pack it with your callback parameters
    register the callback to 3rd party lib
    invoke 3rd party func
    wait on your condition variable
}

void your_callback(Parameters* p)
{
    do whatever...
    notify p->your_cond_variable you have finished
}

      

+1


source


Your best bet due to accessibility and standards is probably using Boost:

Boost.threads for multithreading and Boost :: interprocess for interprocess communication; take a look at IPC synchronization mechanisms .

It is very common for multithreaded applications to have some sort of message queue (at the bottom of the link above) that takes messages in a thread-safe manner from any thread, while another thread in an infinite loop receives messages from that queue. These messages usually include some command, some payload, and a pointer to where the executing thread should put its results. It could be another boost :: interprocess structure.

-1


source







All Articles