// Queue.h : Declaration of the CQueue

#ifndef __QUEUE_H_
#define __QUEUE_H_

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CQueue
class ATL_NO_VTABLE CQueue : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CQueue, &CLSID_Queue>,
	public IGet,
	public IQueue
{
public:
	CQueue();
	HRESULT FinalConstruct();
	~CQueue();

DECLARE_REGISTRY_RESOURCEID(IDR_QUEUE)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CQueue)
	COM_INTERFACE_ENTRY(IQueue)
	COM_INTERFACE_ENTRY(IGet)
END_COM_MAP()

// IGet
public:
	STDMETHOD(Get)(UCHAR*aItem, UINT*aLength, UINT*aTimeout);
	STDMETHOD(Available)(UINT*aLength, UINT*aTimeout);
	STDMETHOD(Clear)();
	STDMETHOD(Interrupt)();
	STDMETHOD(Used)(UINT*aSize);

// IQueue
public:
	STDMETHOD(get_Interface)(/*[out, retval]*/ IGet* *pVal);
	STDMETHOD(put_Interface)(/*[in]*/ IGet* newVal);
	STDMETHOD(Free)(UINT*aSize);

private:
	HRESULT Closeout();
	HRESULT Restart();
	static DWORD WINAPI StartReadLoop(LPVOID lpParameter);
	HRESULT ReadLoop();

private:
	//	This is the size of the buffer (4K)
	enum{BufferSize = 4 * 1024};
	//	Interrupt the get or Available loop
	bool	m_InterruptGet;
	//	Interrupt the read thread
	bool	m_Interrupt;
	//	This is the interface that the characters are coming from
	IGet*	m_Interface;
	//	This is the pointer to where the characters are going in at
	UINT	m_In;
	//	This is the event set when Available needs to be signalled
	bool	m_DoASignal;
	//	This is the event set when the loop begins
	HANDLE	m_Start;
	//	This is the event set when the loop ends
	HANDLE	m_Done;
	//	This is the event set when Available needs to restart
	HANDLE	m_Signal;
	//	This is the event set when Available is restarted
	HANDLE	m_Signaled;
	//	This is the pointer where the characters are coming out at.
	UINT	m_Out;
	//	This indicates the the queue is empty, but the pointers
	//		don't show it yet.
	bool	m_Empty;
	//	This is the buffer which holds the characters.
	UCHAR	m_Buffer[BufferSize];
	//	Semaphore to allow copying in and out atomicly.
	CRITICAL_SECTION m_Copying;
};

#endif //__QUEUE_H_

