/*
 * eventflag.cpp
 */
#include "errno.h"
#include "eventflag.h"


EventFlag::EventFlag(const bool argautoreset) : valid(false), autoreset(argautoreset), flag(0)
{
	init(argautoreset);
}

EventFlag::~EventFlag()
{
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);
}

int EventFlag::init(const bool argautoreset)
{

	int ret;
	ret = ::pthread_cond_init(&cond, NULL);
	if (ret != 0) {
		return(ret);
	}

	ret = ::pthread_mutex_init(&mutex, NULL);
	if (ret != 0) {
		return(ret);
	}

	valid = true;

	return(0);
}

int EventFlag::Wait(const unsigned int pattern)
{

	int ret;
	ret = ::pthread_mutex_lock(&mutex);
	if (ret != 0) {
		return(ret);
	}

	while(!(flag & pattern)) {
		ret = ::pthread_cond_wait(&cond, &mutex);
		if (ret != 0) {
			return(ret);
		}
	}

	if (autoreset) {
		flag &= ~pattern;
	}

	ret = ::pthread_mutex_unlock(&mutex);

	return(ret);

}

int EventFlag::TimedWait(const unsigned int timeout_ms, const unsigned int pattern)
{
    
    int ret;
    ret = ::pthread_mutex_lock(&mutex);
    if (ret != 0) {
        return(ret);
    }
    
    while(!(flag & pattern)) {

        timespec to;
        gettime(&to);
        to.tv_sec += (timeout_ms / 1000);
        to.tv_nsec += ((timeout_ms % 1000) * 1000000);
        if (to.tv_nsec >= 1000000000) {
            to.tv_sec++;
            to.tv_nsec -= 1000000000;
        }
        int tret = ::pthread_cond_timedwait(&cond, &mutex, &to);
        if (tret != 0) {
            ::pthread_mutex_unlock(&mutex);
            return(tret);
        }
    }
    
    if (autoreset) {
        flag &= ~pattern;
    }
    
    ret = ::pthread_mutex_unlock(&mutex);
    
    return(ret);
    
}

int EventFlag::Set(const unsigned int pattern)
{

	int ret;
	ret = ::pthread_mutex_lock(&mutex);
	if (ret != 0) {
		return(ret);
	}

	if (!(flag & pattern)) {

		flag |= pattern;

		ret = ::pthread_cond_broadcast(&cond);
		if (ret != 0) {
			return(ret);
		}
	}

	ret = ::pthread_mutex_unlock(&mutex);

	return(ret);

}

int EventFlag::Reset(const unsigned int pattern)
{

	int ret;
	ret = ::pthread_mutex_lock(&mutex);
	if (ret != 0) {
		return(ret);
	}

	flag &= ~pattern;

	ret = ::pthread_mutex_unlock(&mutex);

	return(ret);


}

