www.pudn.com > NetPaw.rar > async.h


// Async.h: prototypes for the CEventSource and CEventCallback classes. 
// 
// Written by Robert Simpson (robert@blackcastlesoft.com) 
// Created 5/11/2004 
// Version 1.01 -- Last Modified 06/10/2004 
// See Async.cpp for details of this revision 
////////////////////////////////////////////////////////////////////// 
 
#pragma once 
 
#include "threadpool.h" 
 
// Prototypes 
class CEventSource; 
class CEventCallback; 
 
// Standard async result prototype 
typedef VOID (CALLBACK* ASYNCCALLBACK)(CEventSource *, LPVOID, LPVOID, LPVOID, LPVOID, CEventCallback *); 
 
/* Generic callback class, wraps the OVERLAPPED structure to enable class callbacks. 
 
   NOTES 
   ----- 
   It is safe to reuse an instance of this class from within a callback function. 
   It is safe to destroy an instance of this class from within a callback function. 
 
   REGARDING Acquire() AND UnAcquire() 
   --------------------------------- 
   The only time you need to worry about Acquire() and UnAcquire() is if you 
   are using this class as a parameter to a Win32 overlapped I/O function directly. 
   An example would be a class that inherits CEventSource and provides 
   wrappers for overlapped I/O functionality (like CIocpSocket does). 
 
   If this is the case, you MUST call Acquire() to gain exclusive use of the instance. 
   UnAcquire() will be automatically called once the operation completes and 
   before the callback function is executed. 
 
   The only time you need to call UnAcquire() manually is if your overlapped 
   I/O request fails for a reason other than IO_PENDING. 
*/ 
class CEventCallback :  public OVERLAPPED 
{ 
public: 
	typedef CThreadPool2 CBTHREADPOOL; 
 
public: // Constructor 
	CEventCallback(CEventSource *pEventSrc, ASYNCCALLBACK fncb) throw(); 
	~CEventCallback() throw(); 
 
public: // Public member variables 
	// Extra data associated with the callback, call Acquire() 
	// before writing to these members. 
	LPVOID m_Param1; 
	LPVOID m_Param2; 
	LPVOID m_Param3; 
	LPVOID m_Param4; 
   
private: // CThreadPool support functions 
	friend CEventSource; 
	friend CBTHREADPOOL; 
 
	typedef DWORD RequestType; 
 
	// Private constructor, used only by the threadpool 
	CEventCallback(void) throw() : m_pSource(NULL), m_nRefCount(-1) {}; 
 
	BOOL Initialize(LPVOID /* pvWorkerParam */) throw() {return TRUE;}; 
	void Terminate (LPVOID /* pvWorkerParam */) throw() {}; 
	void Execute(RequestType /* req */, LPVOID /* pvWorkerParam */, LPOVERLAPPED pOverlapped) throw() 
	{ 
		CEventCallback *p = static_cast(pOverlapped); 
		p->OnAsyncEvent(); 
	} 
 
	void UnAcquire(BOOL bRelease) throw(); 
 
protected: 
	CEventSource  *m_pSource; 
	ASYNCCALLBACK      m_fncb; 
	volatile LONG      m_nRefCount; 
 
	virtual void OnAsyncEvent() throw(); 
 
public: // Member functions 
 
	// Return a get-only pointer to the underlying event source for this callback 
	// The event source cannot be changed once this class is initialized, but  
	// someone (namely _FakeConnectEx in CIocpSocket) might want to know who ours is. 
	operator CEventSource *(void) const throw() {return m_pSource;} 
 
	BOOL Acquire(void) throw(); 
	void UnAcquire(void) throw(); 
	BOOL Post() throw(); 
 
	static BOOL Post(LPOVERLAPPED pOverlapped) throw(); 
}; 
 
/* Any recipient of asynchronous I/O events needs to inherit CEventSource 
   It is used to ensure all overlapped events are accounted for. 
 
   When your class is cleaning up, first close the handle associated with an IOCP, then 
   call WaitForPending() to ensure all pending I/O events have been accounted for. 
*/ 
class CEventSource 
{ 
public: 
	friend CEventCallback; 
 
public: 
	CEventSource() throw(); 
	~CEventSource() throw(); 
 
private: 
	HANDLE        m_hEventFin; 
	volatile LONG m_nRefCount; 
 
public: 
	BOOL WaitForPending(DWORD dwTimeout = INFINITE) throw(); 
 
private: 
	LONG AddRef(void) throw(); 
	void ReleaseRef(void) throw(); 
 
	static DWORD GetTls() throw(); 
 
public: // Static functions 
	static BOOL Attach(HANDLE hSource) throw(); 
	static BOOL IsThreadInPool(CEventSource *p = NULL) throw(); 
	static CEventCallback::CBTHREADPOOL *GetPool(void) throw(); 
};