示例#1
0
bool SocketLayer::AssociateSocketWithCompletionPortAndRead( SOCKET readSocket, unsigned int binaryAddress, unsigned short port, RakPeer *rakPeer )
{
#ifdef __USE_IO_COMPLETION_PORTS
    assert( readSocket != INVALID_SOCKET );

    ClientContextStruct* ccs = new ClientContextStruct;
    ccs->handle = ( HANDLE ) readSocket;

    ExtendedOverlappedStruct* eos = ExtendedOverlappedPool::Instance()->GetPointer();
    memset( &( eos->overlapped ), 0, sizeof( OVERLAPPED ) );
    eos->binaryAddress = binaryAddress;
    eos->port = port;
    eos->rakPeer = rakPeer;
    eos->length = MAXIMUM_MTU_SIZE;

    bool b = AsynchronousFileIO::Instance()->AssociateSocketWithCompletionPort( readSocket, ( DWORD ) ccs );

    if ( !b )
    {
        ExtendedOverlappedPool::Instance()->ReleasePointer( eos );
        delete ccs;
        return false;
    }

    BOOL success = ReadAsynch( ( HANDLE ) readSocket, eos );

    if ( success == FALSE )
        return false;

#endif

    return true;
}
unsigned __stdcall ThreadPoolFunc( LPVOID arguments )
{
	DWORD dwIoSize;
	ClientContextStruct* lpClientContext;
	ExtendedOverlappedStruct* lpOverlapped;
	LPOVERLAPPED temp;
	BOOL bError;

	HANDLE *completionPort = ( HANDLE * ) arguments;
	AsynchronousFileIO::Instance()->threadCount++;

	while ( 1 )
	{
		// Get a completed IO request.
		BOOL returnValue = GetQueuedCompletionStatus(
			completionPort,
			&dwIoSize,
			( LPDWORD ) & lpClientContext,
			&temp, INFINITE );

		lpOverlapped = ( ExtendedOverlappedStruct* ) temp;

		DWORD dwIOError = GetLastError();

		if ( lpOverlapped == 0 )
			break; // Cancelled thread

		if ( !returnValue && dwIOError != WAIT_TIMEOUT )
		{
			if ( dwIOError != ERROR_OPERATION_ABORTED )
			{
				// Print all but this very common error message
#if defined(_WIN32) && defined(_DEBUG)
				LPVOID messageBuffer;
				FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),  // Default language
					( LPTSTR ) & messageBuffer, 0, NULL );
				// something has gone wrong here...
				printf( "GetQueuedCompletionStatus failed:Error code - %d\n%s", dwIOError, messageBuffer );

				//Free the buffer.
				LocalFree( messageBuffer );
#endif

			}

HANDLE_ERROR:
			// Some kind of error. Erase the data for this call
			bError = true;

			// This socket is no longer used

			if ( lpOverlapped )
				delete lpOverlapped;

			if ( lpClientContext )
				delete lpClientContext;

			// If we are killing the threads, then we keep posting fake completion statuses until we get a fake one through the queue (i.e. lpOverlapped==0 as above)
			// This way we delete all the data from the real calls before exiting the thread
			if ( AsynchronousFileIO::Instance()->killThreads )
			{
				PostQueuedCompletionStatus( completionPort, 0, 0, 0 );
			}

		}

		else
			bError = false;

		if ( !bError )
		{
			if ( returnValue && NULL != lpOverlapped && NULL != lpClientContext )
			{
				if ( lpOverlapped->read == true )
				{
					assert( dwIoSize > 0 );

					ProcessNetworkPacket( lpOverlapped->binaryAddress, lpOverlapped->port, lpOverlapped->data, dwIoSize, lpOverlapped->rakPeer );

					// Issue a new read so we always have one outstanding read per socket
					// Finished a read.  Reuse the overlapped pointer
					bError = ReadAsynch( lpClientContext->handle, lpOverlapped );

					if ( !bError )
						goto HANDLE_ERROR; // Windows is super unreliable!
				}

				else
				{
					// AsynchronousFileIO::Instance()->Write(lpClientContext);
					// Finished a write
					ExtendedOverlappedPool::Instance()->ReleasePointer( lpOverlapped );
				}
			}

			else
				assert( 0 );
		}
	}

	AsynchronousFileIO::Instance()->threadCount--;
	return 0;
}