170 lines
4.4 KiB
C++
170 lines
4.4 KiB
C++
#include "globals.h"
|
|
|
|
#if H323_USE_PRIVATE_IO_THREAD
|
|
#define FINITE_WAIT_TIME 3000
|
|
|
|
static HANDLE H323IoCompletionPort = NULL;
|
|
static HANDLE H323IoThread = NULL;
|
|
static DWORD H323IoThreadID = 0;
|
|
|
|
static DWORD WINAPI H323IoThreadProc (
|
|
IN PVOID ThreadParameter)
|
|
{
|
|
LPOVERLAPPED Overlapped;
|
|
ULONG_PTR CompletionKey;
|
|
DWORD Status;
|
|
DWORD BytesTransferred;
|
|
|
|
for (;;)
|
|
{
|
|
if( GetQueuedCompletionStatus( H323IoCompletionPort,
|
|
&BytesTransferred,
|
|
&CompletionKey,
|
|
&Overlapped,
|
|
INFINITE) == TRUE )
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
if( Overlapped )
|
|
{
|
|
Status = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "failed to dequeue i/o completion "
|
|
"packet: %d, quitting...", GetLastError() ));
|
|
|
|
ExitThread (GetLastError());
|
|
}
|
|
}
|
|
|
|
_ASSERTE( CompletionKey);
|
|
|
|
((LPOVERLAPPED_COMPLETION_ROUTINE) CompletionKey)( Status,
|
|
BytesTransferred,
|
|
Overlapped );
|
|
}
|
|
|
|
// never reached
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
static void CALLBACK H323IoThreadExitCallback (
|
|
IN DWORD Status,
|
|
IN DWORD BytesTransferred,
|
|
IN LPOVERLAPPED Overlapped)
|
|
{
|
|
H323DBG ((DEBUG_LEVEL_TRACE, "i/o completion thread is stopping"));
|
|
ExitThread (EXIT_SUCCESS);
|
|
}
|
|
|
|
HRESULT H323IoThreadStart (void)
|
|
{
|
|
if( H323IoCompletionPort == NULL )
|
|
{
|
|
H323IoCompletionPort =
|
|
CreateIoCompletionPort( INVALID_HANDLE_VALUE,
|
|
NULL,
|
|
0,
|
|
0 );
|
|
if( H323IoCompletionPort == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"failed to create i/o completion port: %d", GetLastError() ));
|
|
|
|
return GetLastResult();
|
|
}
|
|
}
|
|
|
|
|
|
H323IoThread = CreateThread(NULL,
|
|
0,
|
|
H323IoThreadProc,
|
|
NULL,
|
|
0,
|
|
&H323IoThreadID );
|
|
|
|
if( H323IoThread == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"failed to create i/o completion worker thread: %d",
|
|
GetLastError() ));
|
|
|
|
CloseHandle (H323IoCompletionPort);
|
|
H323IoCompletionPort = NULL;
|
|
|
|
return GetLastResult();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void H323IoThreadStop (void)
|
|
{
|
|
DWORD dwWaitTime = INFINITE;
|
|
H323DBG ((DEBUG_LEVEL_WARNING, "H323IoThreadStop entered."));
|
|
|
|
if( H323IoThread != NULL )
|
|
{
|
|
_ASSERTE( H323IoCompletionPort != NULL );
|
|
|
|
if( !PostQueuedCompletionStatus( H323IoCompletionPort, 0,
|
|
(ULONG_PTR) H323IoThreadExitCallback, (LPOVERLAPPED) -1) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING, "PostQueuedCompletionStatus failed" ));
|
|
dwWaitTime = FINITE_WAIT_TIME;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"waiting for i/o completion port thread to finish..." ));
|
|
|
|
WaitForSingleObject( H323IoThread, dwWaitTime );
|
|
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"i/o completion port thread is finished." ));
|
|
|
|
CloseHandle (H323IoThread);
|
|
H323IoThread = NULL;
|
|
}
|
|
|
|
if( H323IoCompletionPort != NULL )
|
|
{
|
|
CloseHandle( H323IoCompletionPort );
|
|
|
|
H323IoCompletionPort = NULL;
|
|
}
|
|
|
|
H323DBG ((DEBUG_LEVEL_WARNING, "H323IoThreadStop exited"));
|
|
}
|
|
|
|
BOOL H323BindIoCompletionCallback (
|
|
IN HANDLE ObjectHandle,
|
|
IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine,
|
|
IN ULONG Flags)
|
|
{
|
|
if( H323IoCompletionPort != NULL )
|
|
{
|
|
if (!CompletionRoutine)
|
|
{
|
|
SetLastError (ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
return CreateIoCompletionPort( ObjectHandle,
|
|
H323IoCompletionPort,
|
|
(ULONG_PTR) CompletionRoutine,
|
|
0 ) != NULL;
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "i/o completion port is not yet created" ));
|
|
|
|
SetLastError( ERROR_GEN_FAILURE );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#endif
|