Search code examples
csocketscallbackandroid-source

Synchronous callbacks in C


I have multiple methods in C DoSomething1(), DoSomething2(), ..., DoSomethingN() that request for some data. These methods can be called concurrently. The data resides in a different process and currently the communication between the current process and that other process is done using a socket.

How can I create a synchronous callback GetSpecialValue() that requests the data using the aforementioned socket and then, when the socket replies, returns the answer back to the specific DoSomethingN() that has requested it?

Keep in mind that I have a lot of methods that work with a single socket and pass requests that their reply should return to the specific method that initiated the call. Those methods work in different threads.

int DoSomethingN(int id) {
    int returnValue = GetSpecialValue(id);
    return returnValue;
}

int GetSpecialValue(int id) {
    SendToProcessViaSocket(id);
    int returnValue = ReceiveSocketAnswer();
    return returnValue;
}

I know that some people use libevent for callbacks, but I don't think that you can return new parameters when the event is called. Also, it's async and isn't part of the AOSP build..

Thanks!


Solution

  • The solution was to lock the thread after the request was passed and then, add the lock to vector that was visible by the thread that handles the requests socket.

    std::tuple<int, pthread_mutex_t *, pthread_cond_t *, bool *> callbackData;
    pthread_mutex_t *reqMutexLock = (pthread_mutex_t *)malloc(sizeof(*reqMutexLock));
    pthread_cond_t *reqCondition = (pthread_cond_t *)malloc(sizeof(*reqCondition));
    bool *state = (bool *)malloc(sizeof(*state));
    
    (*reqMutexLock) = PTHREAD_MUTEX_INITIALIZER;
    (*reqCondition) = PTHREAD_COND_INITIALIZER;
    (*state) = false;
    
    int callbackId = rand();
    
    callbackData = std::make_tuple(callbackId, reqMutexLock, reqCondition, state);
    
    pthread_mutex_lock(reqMutexLock);
    SendRequest(callbackId, id);
    while (!(*state)) {
        pthread_cond_wait(reqCondition, reqMutexLock);
    }
    pthread_mutex_unlock(reqMutexLock);
    pthread_mutex_destroy(reqMutexLock);
    free(reqMutexLock);
    free(reqCondition);
    ...
    

    When the response has returned from the socket, the response would be saved in a responses vector and the lock fetched from the vector and released.

    ...
    response = ReceiveResponse();
    responsesList.push_back(response);
    
    ...
    reqMutexLock = std::get<1>(callbackDataList[foundIndex]);
    reqCondition = std::get<2>(callbackDataList[foundIndex]);
    state = std::get<3>(callbackDataList[foundIndex]);
    
    pthread_mutex_lock(reqMutexLock);
    (*state) = true;
    pthread_cond_broadcast(reqCondition);
    pthread_mutex_unlock(reqMutexLock);
    ...
    

    After the lock was released, the thread would continue and ask for the result, that will be returned from the vector.

    ...
    return GetResponse(callbackId);