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();
};