/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__ASYNC_CALL_QUEUE_THREAD__
#define	__ASYNC_CALL_QUEUE_THREAD__


		#include "async/async_call_queue.h"
		#include "thread/thread_event.h"


namespace GS {
	namespace Threading {

/*!
	@short	A worker thread whose sole purpose is to process its async call queue.
	@author	Emmanuel Julien (ejulien@owloh.com)
*/
class	ASyncCallQueueThread : public Thread
{
		Atomic32	acqt_running;
		Event		queue_event;

		ASync::CallQueue call_queue;

public:

virtual	void		OnIdle() {}

virtual	void		Execute()
		{
			for (acqt_running.Set(1); acqt_running.Get() != 2; )
			{
				call_queue.ExecuteAll();
				OnIdle();
				queue_event.Wait();
			}
			acqt_running.Set(0);
		}
		void		Stop()
		{
			if	(acqt_running.Get() != 0)
			{
				acqt_running.Set(2);
				queue_event.Trigger();
				while (acqt_running.Get() != 0); // spinlock
			}
		}

template <typename I, typename F> void QueueMemberCall(I i, F fn)
		{	call_queue.QueueMemberCall(i, fn); queue_event.Trigger();	}
template <typename I, typename F, typename A1> void QueueMemberCall(I i, F fn, const A1 &a1)
		{	call_queue.QueueMemberCall(i, fn, a1); queue_event.Trigger();	}
template <typename I, typename F, typename A1, typename A2> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2)
		{	call_queue.QueueMemberCall(i, fn, a1, a2); queue_event.Trigger();	}
template <typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
		{	call_queue.QueueMemberCall(i, fn, a1, a2, a3); queue_event.Trigger();	}
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
		{	call_queue.QueueMemberCall(i, fn, a1, a2, a3, a4); queue_event.Trigger();	}

		/// Queue a member call, return the value in a future.
template <typename R, typename I, typename F> void QueueMemberCall(ASync::Future <R> &f, I i, F fn)
		{	call_queue.QueueMemberCall(f, i, fn); queue_event.Trigger();	}
template <typename R, typename I, typename F, typename A1> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1)
		{	call_queue.QueueMemberCall(f, i, fn, a1); queue_event.Trigger();	}
template <typename R, typename I, typename F, typename A1, typename A2> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2)
		{	call_queue.QueueMemberCall(f, i, fn, a1, a2); queue_event.Trigger();	}
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
		{	call_queue.QueueMemberCall(f, i, fn, a1, a2, a3); queue_event.Trigger();	}
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
		{	call_queue.QueueMemberCall(f, i, fn, a1, a2, a3, a4); queue_event.Trigger();	}

virtual	~ASyncCallQueueThread()
		{	Stop();	}
};

	} // Threading
} // GS


#endif	// __ASYNC_CALL_QUEUE_THREAD__
