casynthr.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:13k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #include "hlxclib/windows.h"
- #include "hxresult.h"
- #include "hxslist.h"
- #include "hxcom.h"
- #include "hxengin.h"
- #include "hxthread.h"
- #include "conn.h"
- #include "thrdconn.h"
- #include "threngin.h"
- #include "platform/win/casynthr.h"
- #include "hxmap.h"
- #include "hxassert.h"
- #include "hxstrutl.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #ifdef WIN32_PLATFORM_PSPC
- #define WM_NCCREATE WM_CREATE
- #define WM_NCDESTROY WM_DESTROY
- #define WND_CLASS_BASE L"HX_Internal_NetThread_Async"
- #else
- #define WND_CLASS_BASE "HX_Internal_NetThread_Async"
- #endif
- #define MAX_WND_CLASS_LENGTH 50
- #ifdef _WIN32
- UINT CAsyncNetThread::zm_uDestroyMessage = 0;
- #endif
- #define OFFSET_THIS 0
- BOOL CAsyncNetThread::zm_bClassRegistered = FALSE;
- CAsyncNetThread* CAsyncNetThread::zm_pSockNotifiers = NULL;
- CAsyncNetThread*
- CAsyncNetThread::GetCAsyncNetThreadNotifier(HINSTANCE hInst, BOOL Create)
- {
- CAsyncNetThread* pThis = 0;
- // Does our current session already has a notifier?
- if (!(pThis = FindNetThreadNotifier()) && Create)
- {
- // No, then create one
- pThis = new CAsyncNetThread(hInst);
- if (pThis && !pThis->IsValid())
- {
- // If creation failed then delete the pointer
- delete pThis;
- pThis = NULL;
- }
- if (pThis)
- {
- LinkUs(pThis);
- }
- }
- return (pThis);
- }
- ULONG32 CAsyncNetThread::GetSession()
- {
- #if defined( _WIN32 )
- return (GetCurrentThreadId());
- #else
- return ((ULONG32)(LPSTR)GetCurrentTask());
- #endif
- }
- CAsyncNetThread::CAsyncNetThread(HINSTANCE hInst)
- : m_hWnd(NULL)
- , m_bValid(FALSE)
- , m_hInst(hInst)
- , m_nNumSocketsClients(0)
- , m_bInCancelMode(FALSE)
- , m_pNextNotifier(0)
- , m_pThreadEngineMutex(0)
- {
- #ifdef _WIN32
- if (!zm_uDestroyMessage)
- {
- zm_uDestroyMessage = RegisterWindowMessage(OS_STRING("HX_DestroyInternalNetThreadAsync"));
- }
- #endif
- m_ClientSocketsMap = new CHXMapPtrToPtr;
- m_ulSession = CAsyncNetThread::GetSession();
- m_bValid = Create();
- ThreadEngine* pEngine = ThreadEngine::GetThreadEngine();
- m_pThreadEngineMutex = pEngine->GetMutex();
- }
- // Workhorse construction method
- BOOL CAsyncNetThread::Create()
- {
- char szClassName[MAX_WND_CLASS_LENGTH]; /* Flawfinder: ignore */
- SafeSprintf(szClassName, MAX_WND_CLASS_LENGTH, OS_STRING("%s%d"),
- WND_CLASS_BASE, &zm_bClassRegistered);
- if (!zm_bClassRegistered)
- {
- WNDCLASS internalClass;
- OS_STRING_TYPE osstrClassName(szClassName);
- // First register our window class
- internalClass.style = 0;
- internalClass.lpfnWndProc = CAsyncNetThread::AsyncNotifyProc;
- internalClass.cbClsExtra = 0;
- internalClass.cbWndExtra = sizeof(this);
- internalClass.hInstance = m_hInst; // Use app's instance
- internalClass.hIcon = 0;
- internalClass.hCursor = 0;
- internalClass.hbrBackground = 0;
- internalClass.lpszMenuName = NULL;
- internalClass.lpszClassName = osstrClassName;
-
- zm_bClassRegistered = RegisterClass(&internalClass);
-
- if(!zm_bClassRegistered)
- {
- UnregisterClass(OS_STRING(szClassName), m_hInst);
- zm_bClassRegistered = RegisterClass(&internalClass);
- }
- }
- // Now create an instance of the window
- m_hWnd = ::CreateWindow(OS_STRING(szClassName), OS_STRING("RealMedia Internal Messages"),
- WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, m_hInst, this);
-
- if (!m_hWnd)
- {
- return (FALSE);
- }
- return (TRUE);
- }
- // Destructor: Destroys the window and unregisters the class if necessary
- CAsyncNetThread::~CAsyncNetThread()
- {
- m_bValid = FALSE;
- m_hWnd = NULL;
- m_hInst = NULL;
- if(m_ClientSocketsMap)
- {
- delete m_ClientSocketsMap;
- m_ClientSocketsMap = NULL;
- m_nNumSocketsClients = 0;
- }
- }
- LRESULT HXEXPORT
- CAsyncNetThread::AsyncNotifyProc(HWND hWnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
- {
- CAsyncNetThread* pThis = 0;
- if (msg == WM_NCCREATE)
- {
- CREATESTRUCT* lpCreate = 0;
- // Set our this pointer, so our WndProc can find us again
- lpCreate = (CREATESTRUCT FAR*) lParam;
- pThis = (CAsyncNetThread*) lpCreate->lpCreateParams;
- SetWindowLong(hWnd, OFFSET_THIS, (long) pThis);
- }
- else if (msg == WM_NCDESTROY)
- {
- // remove our this pointer so if somebody calls this function
- // again after the window is gone (and the object is gone
- // too) we don't try to call a method from the pointer
- SetWindowLong(hWnd, OFFSET_THIS, 0L);
- }
- else
- {
- pThis = (CAsyncNetThread*) (LPHANDLE)GetWindowLong(hWnd, OFFSET_THIS);
- }
- if (pThis != NULL)
- {
- switch (msg)
- {
- case HXMSG_ASYNC_DNS:
- return (pThis->OnAsyncDNS(wParam, lParam));
- case HXMSG_ASYNC_CONNECT:
- return (pThis->OnAsyncConnect(wParam, lParam));
- case HXMSG_ASYNC_READ:
- return (pThis->OnAsyncRead(wParam, lParam));
- case HXMSG_ASYNC_WRITE:
- return (pThis->OnAsyncWrite(wParam, lParam));
- case HXMSG_ASYNC_ACCEPT:
- return (pThis->OnAsyncAccept(wParam, lParam));
- default:
- break;
- }
- }
- #ifdef _WIN32
- if (msg == zm_uDestroyMessage)
- {
- LRESULT result = DestroyWindow(hWnd);
- delete pThis;
- return result;
- }
- #endif
- return (DefWindowProc(hWnd, msg, wParam, lParam));
- }
- LRESULT CAsyncNetThread::CheckClients()
- {
- if (!m_bInCancelMode && m_nNumSocketsClients == 0)
- {
- MSG msg;
- while (m_hWnd && PeekMessage(&msg, m_hWnd,0,0,PM_REMOVE))
- {
- if(msg.message == WM_QUIT)
- {
- // When peeking WM_QUIT message in the main thread of an application
- // we have to put it back into message queue to allow the application
- // to exit correctly. SB
- PostQuitMessage(0);
- break;
- }
- else
- {
- // This will remove any messages!
- HX_TRACE("There's a message that would've go you!!rn");
- /* We do not care about these messages any more */
- #ifdef HELIX_FEATURE_NETWORK_USE_SELECT
- // peek doesn't remove wm_paint, this becomes an infinite loop
- if (msg.message == WM_PAINT)
- DispatchMessage(&msg);
- #endif
- }
- }
- UnlinkUs(this);
- /* If we are in the same thread on which the window was created,
- * call SendMessage else post a message and Sleep to perform
- * thread context switch
- */
- if (m_ulSession == CAsyncNetThread::GetSession())
- {
- SendMessage(m_hWnd, zm_uDestroyMessage, 0, 0);
- }
- else
- {
- PostMessage(m_hWnd, zm_uDestroyMessage, 0, 0);
- Sleep(0);
- }
- }
- return(TRUE);
- }
- // Inserts us at the head of the list
- void
- CAsyncNetThread::LinkUs(CAsyncNetThread* pUs)
- {
- HX_ASSERT(pUs);
- if (!pUs)
- {
- return;
- }
- // Tack us on at the head of the list since order doesn't matter
- pUs->m_pNextNotifier = zm_pSockNotifiers;
- zm_pSockNotifiers = pUs;
- }
- // Removes us from the list
- void
- CAsyncNetThread::UnlinkUs(CAsyncNetThread* pUs)
- {
- CAsyncNetThread* pWalk = 0;
- HX_ASSERT(pUs);
- // Don't try to remove NULL pointers
- if (!pUs)
- {
- return;
- }
- if (zm_pSockNotifiers == pUs)
- {
- zm_pSockNotifiers = pUs->m_pNextNotifier;
- return;
- }
- else
- {
- pWalk = zm_pSockNotifiers;
- while (pWalk && (pWalk->m_pNextNotifier != pUs))
- {
- pWalk = pWalk->m_pNextNotifier;
- }
- // Did we find ourselves?
- if (pWalk)
- {
- // Ok, link to our successor
- pWalk->m_pNextNotifier = pUs->m_pNextNotifier;
- }
- }
- return;
- }
- // Returns correct notifier object for our current session (thread/task)
- CAsyncNetThread*
- CAsyncNetThread::FindNetThreadNotifier()
- {
- ULONG32 ulSession;
- CAsyncNetThread* pWalk;
- ulSession = CAsyncNetThread::GetSession();
- pWalk = CAsyncNetThread::zm_pSockNotifiers;
- while (pWalk && pWalk->m_ulSession != ulSession)
- {
- pWalk = pWalk->m_pNextNotifier;
- }
-
- return (pWalk);
- }
- HX_RESULT
- CAsyncNetThread::AttachSocket(ThreadedConn* pSocket)
- {
- void* pVoid = 0;
- HX_RESULT theErr = HXR_OK;
- // Preliminary checks
- HX_ASSERT(this);
- HX_ASSERT(pSocket);
- // Bail on bad input
- if (!this || !pSocket)
- {
- theErr = HXR_FAIL;
- goto exit;
- }
- if (!m_ClientSocketsMap->Lookup((void*)pSocket, pVoid))
- {
- pSocket->AddRef();
- m_ClientSocketsMap->SetAt((void*)pSocket, (void*)pSocket);
- // Bump our client count up
- IncrementSocketsClientCount();
- }
- else
- {
- theErr = HXR_FAIL;
- }
- exit:
- return theErr;
- }
- HX_RESULT
- CAsyncNetThread::DetachSocket(ThreadedConn* pSocket)
- {
- HX_RESULT theErr = HXR_OK;
- // Preliminary checks
- HX_ASSERT(this);
- HX_ASSERT(pSocket);
- // Bail on bad input
- if (!this || !pSocket)
- {
- theErr = HXR_FAIL;
- goto exit;
- }
- if (m_ClientSocketsMap)
- {
- if (m_ClientSocketsMap->RemoveKey((void*)pSocket))
- {
- pSocket->Release();
- DecrementSocketsClientCount();
- }
- }
- CheckClients();
- exit:
- return theErr;
- }
- LRESULT
- CAsyncNetThread::OnAsyncDNS(WPARAM wParam, LPARAM lParam)
- {
- // m_pThreadEngineMutex->Lock();
- void* pVoid = 0;
- if (!m_ClientSocketsMap ||
- !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
- {
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- ThreadedConn* pConnection = (ThreadedConn*) pVoid;
- pConnection->OnAsyncDNS((BOOL) lParam);
-
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- LRESULT
- CAsyncNetThread::OnAsyncConnect(WPARAM wParam, LPARAM lParam)
- {
- // m_pThreadEngineMutex->Lock();
- void* pVoid = 0;
- if (!m_ClientSocketsMap ||
- !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
- {
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- ThreadedConn* pConnection = (ThreadedConn*) pVoid;
- pConnection->OnConnect((BOOL) lParam);
-
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- LRESULT
- CAsyncNetThread::OnAsyncRead(WPARAM wParam, LPARAM lParam)
- {
- // m_pThreadEngineMutex->Lock();
- void* pVoid = 0;
- if (!m_ClientSocketsMap ||
- !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
- {
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- ThreadedConn* pConnection = (ThreadedConn*) pVoid;
- pConnection->OnReadNotification();
-
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- LRESULT
- CAsyncNetThread::OnAsyncWrite(WPARAM wParam, LPARAM lParam)
- {
- // m_pThreadEngineMutex->Lock();
- void* pVoid = 0;
- if (!m_ClientSocketsMap ||
- !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
- {
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- ThreadedConn* pConnection = (ThreadedConn*) pVoid;
- pConnection->OnWriteNotification();
-
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- LRESULT
- CAsyncNetThread::OnAsyncAccept(WPARAM wParam, LPARAM lParam)
- {
- // m_pThreadEngineMutex->Lock();
- void* pVoid = 0;
- if (!m_ClientSocketsMap ||
- !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
- {
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }
- ThreadedConn* pConnection = (ThreadedConn*) pVoid;
- pConnection->OnAcceptNotification();
-
- // m_pThreadEngineMutex->Unlock();
- return TRUE;
- }