// Eventcpp.h V0.1pre Member functions for class Event, an automatic/manual reset event object.
// © 2003 Elliot Nierman


#include "event.h"

Event::Event()

{
#ifdef WIN
    event = CreateEvent(NULL, false, false, NULL);
#endif

#ifdef POSIX

    bool signal = false;
    bool manual = false;
    bool pulse = false;

    waiters = 0;
    pthread_cond_init(&p_event, NULL);

#endif

}


Event::Event(bool Manual_Reset)
{
#ifdef WIN
    event = CreateEvent(NULL, Manual_Reset, false, NULL);
#endif

#ifdef POSIX

    signal = false;
    manual = true;
    pulse = false;

    pthread_cond_init(&p_event, NULL);

#endif

}
//Signal( )
// Automatic-Reset - If no waiting threads, signaled state is maintained,
// otherwise one thread is released.
// Manual-Reset - Event state set to signaled, all waiting threads are
// released, and signaled state is maintained
void Event::Signal()
{
#ifdef WIN
    SetEvent(event);
#endif

#ifdef POSIX

if(manual)
{
    pthread_mutex_lock(&event_mtx);
    signal = true;
    pthread_cond_broadcast(&p_event);
    pthread_mutex_unlock(&event_mtx);

} //end manual set
else
{
    pthread_mutex_lock(&event_mtx);
    if (waiters == 0)
    {
        pulse = true;
        pthread_mutex_unlock(&event_mtx);
    }
    else
    {

    pthread_cond_signal(&p_event);
    pthread_mutex_unlock(&event_mtx);
}

}
#endif

}

//Reset( )
// Automatic-Reset - No effect.
// Manual-Reset - State of event is set to non-signaled
void Event::Reset()
{
#ifdef WIN
    ResetEvent(event);
#endif

#ifdef POSIX
    if(manual)
    {
        pthread_mutex_lock(&event_mtx);
        signal = false;
        pthread_mutex_unlock(&event_mtx);
    }
#endif

}


//Pulse( )
// Automatic-Reset - If waiting threads exist, one is released
// Manual-Reset - If waiting threads exist, all aer released
void Event::Pulse()
{
#ifdef WIN
    PulseEvent(event);
#endif

#ifdef POSIX

    pthread_mutex_lock(&event_mtx);

    if(manual)
    {
        pthread_cond_broadcast(&p_event);
        pthread_mutex_unlock(&event_mtx);
        return;
    }
    else
    {
        pthread_cond_signal(&p_event);
        pthread_mutex_unlock(&event_mtx);
    }//end auto else
#endif

}

Event::~Event()
{
#ifdef WIN
    CloseHandle(event);
#endif

#ifdef POSIX
    pthread_cond_destroy(&p_event);
#endif

}


//Wait( )
// Function to issue a wait request on an event object.
void Event::Wait()
{
#ifdef WIN
    WaitForSingleObject(event,INFINITE);
#endif

#ifdef POSIX

    pthread_mutex_lock(&event_mtx);
    waiters++;

    if (manual)
    {
        if(pulse)
           {
            pulse = false;
            waiters--;
            pthread_mutex_unlock(&event_mtx);
            return;
            }//end pulse if

         if(signal == false)
        {

            pthread_cond_wait(&p_event, &event_mtx);
            waiters--;
            pthread_mutex_unlock(&event_mtx );
            return;
         } //end !signal if
            else
            {
                waiters--;
                pthread_mutex_unlock(&event_mtx);
                return;
             }

    } //end manual wait

    else
    {
    if(pulse)
        {
        pulse = false;
        waiters--;
        pthread_mutex_unlock(&event_mtx);
        return;
        }
    else
        {
        pthread_cond_wait(&p_event, &event_mtx);
        waiters--;
        pthread_mutex_unlock(&event_mtx);
        return;
        }



    }//end manual if
#endif
}