/*
 * QrfeJobDispatcher.cpp
 *
 *  Created on: 31.01.2011
 *      Author: stefan.detter
 */

#include "../inc/QrfeJobDispatcher.h"

ulong QrfeJobReceiver::m_componentCounter = 0;

QrfeJobDispatcher::QrfeJobDispatcher()
{
}

QrfeJobDispatcher::~QrfeJobDispatcher()
{
	foreach(QSemaphore* sem, m_jobNotifier.values()){
		delete sem;
	}
	m_jobNotifier.clear();
}

int QrfeJobDispatcher::jobCount   ( ulong receiverId )
{
	m_jobNotifierMutex.lock();
	QSemaphore* sem = 0;
	if(m_jobNotifier.contains(receiverId))
		sem = m_jobNotifier[receiverId];
	m_jobNotifierMutex.unlock();

	if(sem == 0)
		return 0;

	QMutexLocker lock(&m_jobDataMutex);
	return m_jobData[receiverId].size();
}

bool QrfeJobDispatcher::waitForJob ( ulong receiverId, QrfeJobData& job, ulong maxWaitTime )
{
	m_jobNotifierMutex.lock();
	QSemaphore* sem = 0;
	if(m_jobNotifier.contains(receiverId))
		sem = m_jobNotifier[receiverId];
	m_jobNotifierMutex.unlock();

	if(sem == 0)
	{
		m_jobNotifierMutex.lock();
		m_jobNotifier[receiverId] = sem = new QSemaphore();
		m_jobNotifierMutex.unlock();
	}

	while(1)
	{
		if(!sem->tryAcquire(1, maxWaitTime))
			return false;

		bool res = false;

		m_jobDataMutex.lock();
		if(m_jobData.contains(receiverId) && m_jobData.value(receiverId).size() > 0)
		{
			job = m_jobData[receiverId].takeFirst();
			res = true;
		}
		m_jobDataMutex.unlock();

		return res;
	}
	
	return false;
}

void QrfeJobDispatcher::removeJobs ( ulong receiverId )
{
	m_jobNotifierMutex.lock();
	QSemaphore* sem = 0;
	if(m_jobNotifier.contains(receiverId))
		sem = m_jobNotifier[receiverId];
	m_jobNotifierMutex.unlock();

	if(sem == 0)
		return;

	while(1)
	{
		if(!sem->tryAcquire(1, 1))
			return;

		m_jobDataMutex.lock();
		if(m_jobData.contains(receiverId) && m_jobData.value(receiverId).size() > 0)
		{
			m_jobData[receiverId].takeFirst();
		}
		m_jobDataMutex.unlock();
	}
}

void QrfeJobDispatcher::insertJob ( ulong receiverId, ulong jobId, QList<QVariant> params)
{
	insertJob(QList<ulong>() << receiverId, jobId, params);
}

void QrfeJobDispatcher::insertJob ( QList<ulong> receiverIds, ulong jobId, QList<QVariant> params )
{
	QrfeJobData job;
	job.jobId 	= jobId;
	job.params 	= params;
	foreach(ulong receiverId, receiverIds)
	{
		m_jobDataMutex.lock();
		m_jobData[receiverId].append(job);
		m_jobDataMutex.unlock();

		m_jobNotifierMutex.lock();
		QSemaphore* sem = 0;
		if(m_jobNotifier.contains(receiverId))
			sem = m_jobNotifier[receiverId];
		m_jobNotifierMutex.unlock();

		if(sem == 0)
		{
			m_jobNotifierMutex.lock();
			m_jobNotifier[receiverId] = sem = new QSemaphore();
			m_jobNotifierMutex.unlock();
		}

		sem->release();

		QMetaObject::invokeMethod(this, "_q_emitSignal", Qt::QueuedConnection, Q_ARG(ulong, receiverId) );
	}
}

void QrfeJobDispatcher::_q_emitSignal(ulong receiverId)
{
	emit jobInserted(receiverId);
}
