
#include <stdlib.h>
#include <pthread.h>

#include "responseholder.h"

#define MESSAGE_WAIT_SECONDS (5 * 60)

struct s_ResponseHolder
{
    int sequence;

    pthread_cond_t cond;
    pthread_mutex_t mutex;

    Message *response;
};

ResponseHolder *
responseholder_new (int seq)
{
    ResponseHolder *resp = malloc (sizeof (ResponseHolder));

    resp->sequence = seq;

    pthread_cond_init (&resp->cond, NULL);
    pthread_mutex_init (&resp->mutex, NULL);

    resp->response = NULL;

    return (resp);
}

void
responseholder_destroy (void *ptr)
{
    ResponseHolder *resp = (ResponseHolder *) ptr;

    pthread_cond_destroy (&resp->cond);
    pthread_mutex_destroy (&resp->mutex);

    free (resp);
}

Message *
responseholder_getResponse (ResponseHolder *resp)
{
    Message *messageResponse = NULL;

    pthread_mutex_lock (&resp->mutex);

    if (resp->response == NULL)
    {
        struct timespec timeout;

        timeout.tv_sec = time(0) + MESSAGE_WAIT_SECONDS;
        timeout.tv_nsec = 0;

        /* 
         * if this returns, we've either got our signal, or we timed out,
         * either way, we're done waiting.
         */
        pthread_cond_timedwait (&resp->cond, &resp->mutex, &timeout);
    }

    messageResponse = resp->response;

    pthread_mutex_unlock (&resp->mutex);

    return (messageResponse);
}

void
responseholder_setResponse (ResponseHolder *resp, Message *message)
{
    pthread_mutex_lock (&resp->mutex);

    resp->response = message;

    pthread_mutex_unlock (&resp->mutex);

    pthread_cond_signal (&resp->cond);
}

