casynthr.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:13k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include "hlxclib/windows.h"
  37. #include "hxresult.h"
  38. #include "hxslist.h"
  39. #include "hxcom.h"
  40. #include "hxengin.h"
  41. #include "hxthread.h"
  42. #include "conn.h"
  43. #include "thrdconn.h"
  44. #include "threngin.h"
  45. #include "platform/win/casynthr.h"
  46. #include "hxmap.h"
  47. #include "hxassert.h"
  48. #include "hxstrutl.h"
  49. #include "hxheap.h"
  50. #ifdef _DEBUG
  51. #undef HX_THIS_FILE
  52. static const char HX_THIS_FILE[] = __FILE__;
  53. #endif  
  54. #ifdef WIN32_PLATFORM_PSPC
  55. #define WM_NCCREATE WM_CREATE
  56. #define WM_NCDESTROY WM_DESTROY
  57. #define WND_CLASS_BASE L"HX_Internal_NetThread_Async"
  58. #else
  59. #define WND_CLASS_BASE "HX_Internal_NetThread_Async"
  60. #endif
  61. #define MAX_WND_CLASS_LENGTH 50
  62. #ifdef _WIN32
  63. UINT CAsyncNetThread::zm_uDestroyMessage = 0;
  64. #endif
  65. #define OFFSET_THIS 0
  66. BOOL     CAsyncNetThread::zm_bClassRegistered    = FALSE;
  67. CAsyncNetThread*    CAsyncNetThread::zm_pSockNotifiers     = NULL;
  68. CAsyncNetThread*
  69. CAsyncNetThread::GetCAsyncNetThreadNotifier(HINSTANCE hInst, BOOL Create)
  70. {
  71.     CAsyncNetThread* pThis = 0;
  72.     // Does our current session already has a notifier?
  73.     if (!(pThis = FindNetThreadNotifier()) && Create)
  74.     {
  75. // No, then create one
  76. pThis = new CAsyncNetThread(hInst);
  77. if (pThis && !pThis->IsValid())
  78. {
  79.     // If creation failed then delete the pointer
  80.     delete pThis;
  81.     pThis = NULL;
  82. }
  83. if (pThis)
  84. {
  85.     LinkUs(pThis);
  86. }
  87.     }
  88.     return (pThis);
  89. }
  90. ULONG32 CAsyncNetThread::GetSession()
  91. {
  92. #if defined( _WIN32 )
  93. return (GetCurrentThreadId());
  94. #else
  95. return ((ULONG32)(LPSTR)GetCurrentTask());
  96. #endif
  97. }
  98. CAsyncNetThread::CAsyncNetThread(HINSTANCE hInst)
  99.     : m_hWnd(NULL)
  100.     , m_bValid(FALSE)
  101.     , m_hInst(hInst)
  102.     , m_nNumSocketsClients(0)
  103.     , m_bInCancelMode(FALSE)
  104.     , m_pNextNotifier(0)
  105.     , m_pThreadEngineMutex(0)
  106. {
  107. #ifdef _WIN32
  108.     if (!zm_uDestroyMessage)
  109.     {
  110. zm_uDestroyMessage = RegisterWindowMessage(OS_STRING("HX_DestroyInternalNetThreadAsync"));
  111.     }
  112. #endif
  113.     m_ClientSocketsMap = new CHXMapPtrToPtr;
  114.     m_ulSession = CAsyncNetThread::GetSession();
  115.     m_bValid = Create();
  116.     ThreadEngine* pEngine   = ThreadEngine::GetThreadEngine();
  117.     m_pThreadEngineMutex    = pEngine->GetMutex();
  118. }
  119. // Workhorse construction method
  120. BOOL CAsyncNetThread::Create()
  121. {
  122. char szClassName[MAX_WND_CLASS_LENGTH]; /* Flawfinder: ignore */
  123.     SafeSprintf(szClassName, MAX_WND_CLASS_LENGTH, OS_STRING("%s%d"), 
  124.      WND_CLASS_BASE, &zm_bClassRegistered);
  125. if (!zm_bClassRegistered)
  126.     {
  127. WNDCLASS internalClass;
  128.     OS_STRING_TYPE osstrClassName(szClassName);
  129. // First register our window class                                  
  130. internalClass.style  = 0;
  131. internalClass.lpfnWndProc  = CAsyncNetThread::AsyncNotifyProc;
  132. internalClass.cbClsExtra = 0;
  133. internalClass.cbWndExtra = sizeof(this);
  134. internalClass.hInstance = m_hInst; // Use app's instance
  135. internalClass.hIcon = 0;
  136. internalClass.hCursor = 0;
  137. internalClass.hbrBackground = 0;
  138. internalClass.lpszMenuName = NULL;
  139. internalClass.lpszClassName = osstrClassName;
  140. zm_bClassRegistered = RegisterClass(&internalClass);
  141. if(!zm_bClassRegistered)
  142. {
  143.     UnregisterClass(OS_STRING(szClassName), m_hInst);
  144.     zm_bClassRegistered = RegisterClass(&internalClass);
  145. }
  146.     }
  147.     // Now create an instance of the window
  148.     m_hWnd = ::CreateWindow(OS_STRING(szClassName), OS_STRING("RealMedia Internal Messages"), 
  149. WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, m_hInst, this);
  150.  
  151.     if (!m_hWnd)
  152.     {
  153. return (FALSE);
  154.     }
  155.     return (TRUE);
  156. }
  157. // Destructor: Destroys the window and unregisters the class if necessary
  158. CAsyncNetThread::~CAsyncNetThread()
  159. {
  160.     m_bValid = FALSE;
  161.     m_hWnd  = NULL;
  162.     m_hInst = NULL;
  163.     if(m_ClientSocketsMap)
  164.     {
  165. delete m_ClientSocketsMap;
  166. m_ClientSocketsMap = NULL;
  167. m_nNumSocketsClients = 0;
  168.     }
  169. }
  170. LRESULT HXEXPORT 
  171. CAsyncNetThread::AsyncNotifyProc(HWND hWnd, UINT msg, 
  172.  WPARAM wParam, LPARAM lParam)
  173. {
  174.     CAsyncNetThread*    pThis = 0;
  175.     if (msg == WM_NCCREATE)
  176.     {
  177. CREATESTRUCT* lpCreate = 0;
  178. // Set our this pointer, so our WndProc can find us again
  179. lpCreate = (CREATESTRUCT FAR*) lParam;
  180. pThis = (CAsyncNetThread*) lpCreate->lpCreateParams;
  181. SetWindowLong(hWnd, OFFSET_THIS, (long) pThis);
  182.     }
  183.     else if (msg == WM_NCDESTROY)
  184.     {
  185. // remove our this pointer so if somebody calls this function
  186. // again after the window is gone (and the object is gone
  187. // too) we don't try to call a method from the pointer
  188. SetWindowLong(hWnd, OFFSET_THIS, 0L);
  189.     }
  190.     else
  191.     {
  192. pThis = (CAsyncNetThread*) (LPHANDLE)GetWindowLong(hWnd, OFFSET_THIS);
  193.     }
  194.     if (pThis != NULL)
  195.     {
  196. switch (msg)
  197. {
  198.     case HXMSG_ASYNC_DNS:
  199. return (pThis->OnAsyncDNS(wParam, lParam));
  200.     case HXMSG_ASYNC_CONNECT:
  201. return (pThis->OnAsyncConnect(wParam, lParam));
  202.     case HXMSG_ASYNC_READ:
  203. return (pThis->OnAsyncRead(wParam, lParam));
  204.     case HXMSG_ASYNC_WRITE:
  205. return (pThis->OnAsyncWrite(wParam, lParam));
  206.     case HXMSG_ASYNC_ACCEPT:
  207. return (pThis->OnAsyncAccept(wParam, lParam));
  208.     default:
  209. break;
  210. }
  211.     }
  212. #ifdef _WIN32
  213.     if (msg == zm_uDestroyMessage)
  214.     {
  215. LRESULT result = DestroyWindow(hWnd);
  216. delete pThis;
  217. return result;
  218.     }
  219. #endif
  220.     return (DefWindowProc(hWnd, msg, wParam, lParam));
  221. }
  222. LRESULT CAsyncNetThread::CheckClients()
  223. {
  224.     if (!m_bInCancelMode && m_nNumSocketsClients == 0)
  225.     {
  226. MSG msg;
  227. while (m_hWnd && PeekMessage(&msg, m_hWnd,0,0,PM_REMOVE))
  228. {
  229.     if(msg.message == WM_QUIT) 
  230.     {   
  231. // When peeking WM_QUIT message in the main thread of an application 
  232. // we have to put it back into message queue to allow the application 
  233. // to exit correctly. SB
  234. PostQuitMessage(0);
  235. break;
  236.     }
  237.     else
  238.     {
  239. // This will remove any messages!
  240. HX_TRACE("There's a message that would've go you!!rn");
  241. /* We do not care about these messages any more */
  242. #ifdef HELIX_FEATURE_NETWORK_USE_SELECT
  243. // peek doesn't remove wm_paint, this becomes an infinite loop
  244. if (msg.message == WM_PAINT)
  245.     DispatchMessage(&msg);
  246. #endif
  247.     }
  248. }
  249. UnlinkUs(this);
  250. /* If we are in the same thread on which the window was created,
  251.  * call SendMessage else post a message and Sleep to perform
  252.  * thread context switch
  253.  */
  254. if (m_ulSession == CAsyncNetThread::GetSession())
  255. {
  256.     SendMessage(m_hWnd, zm_uDestroyMessage, 0, 0);
  257. }
  258. else
  259. {
  260.     PostMessage(m_hWnd, zm_uDestroyMessage, 0, 0);
  261.     Sleep(0);
  262. }
  263.     }
  264.     return(TRUE);
  265. }
  266. // Inserts us at the head of the list
  267. void 
  268. CAsyncNetThread::LinkUs(CAsyncNetThread* pUs)
  269. {
  270.     HX_ASSERT(pUs);
  271.     if (!pUs)
  272.     {
  273. return;
  274.     }
  275.     // Tack us on at the head of the list since order doesn't matter
  276.     pUs->m_pNextNotifier = zm_pSockNotifiers;
  277.     zm_pSockNotifiers = pUs;
  278. }
  279. // Removes us from the list
  280. void 
  281. CAsyncNetThread::UnlinkUs(CAsyncNetThread* pUs)
  282. {
  283.     CAsyncNetThread* pWalk = 0;
  284.     HX_ASSERT(pUs);
  285.     // Don't try to remove NULL pointers
  286.     if (!pUs)
  287.     {
  288. return;
  289.     }
  290.     if (zm_pSockNotifiers == pUs)
  291.     {
  292. zm_pSockNotifiers = pUs->m_pNextNotifier;
  293. return;
  294.     }
  295.     else
  296.     {
  297. pWalk = zm_pSockNotifiers;
  298. while (pWalk && (pWalk->m_pNextNotifier != pUs))
  299. {
  300.     pWalk = pWalk->m_pNextNotifier;
  301. }
  302. // Did we find ourselves?
  303. if (pWalk)
  304. {
  305.     // Ok, link to our successor
  306.     pWalk->m_pNextNotifier = pUs->m_pNextNotifier;
  307. }
  308.     }
  309.     return;
  310. }
  311. // Returns correct notifier object for our current session (thread/task)
  312. CAsyncNetThread*
  313. CAsyncNetThread::FindNetThreadNotifier()
  314. {
  315.     ULONG32     ulSession;
  316.     CAsyncNetThread*    pWalk;
  317.     ulSession = CAsyncNetThread::GetSession();
  318.     pWalk = CAsyncNetThread::zm_pSockNotifiers;
  319.     while (pWalk && pWalk->m_ulSession != ulSession)
  320.     {
  321. pWalk = pWalk->m_pNextNotifier;
  322.     }
  323.     
  324.     return (pWalk);
  325. }
  326. HX_RESULT
  327. CAsyncNetThread::AttachSocket(ThreadedConn* pSocket)
  328. {
  329.     void* pVoid = 0;
  330.     HX_RESULT theErr = HXR_OK;
  331.     // Preliminary checks
  332.     HX_ASSERT(this);
  333.     HX_ASSERT(pSocket);
  334.     // Bail on bad input
  335.     if (!this || !pSocket)
  336.     {
  337. theErr = HXR_FAIL;
  338. goto exit;
  339.     }
  340.     if (!m_ClientSocketsMap->Lookup((void*)pSocket, pVoid))
  341.     {
  342. pSocket->AddRef();
  343. m_ClientSocketsMap->SetAt((void*)pSocket, (void*)pSocket);
  344. // Bump our client count up
  345. IncrementSocketsClientCount();
  346.     }
  347.     else
  348.     {
  349. theErr = HXR_FAIL;
  350.     }
  351. exit:
  352.     return theErr;
  353. }
  354. HX_RESULT
  355. CAsyncNetThread::DetachSocket(ThreadedConn* pSocket)
  356. {
  357.     HX_RESULT theErr = HXR_OK;
  358.     // Preliminary checks
  359.     HX_ASSERT(this);
  360.     HX_ASSERT(pSocket);
  361.     // Bail on bad input
  362.     if (!this || !pSocket)
  363.     {
  364. theErr = HXR_FAIL;
  365. goto exit;
  366.     }
  367.     if (m_ClientSocketsMap)
  368.     {
  369. if (m_ClientSocketsMap->RemoveKey((void*)pSocket))
  370. {
  371.     pSocket->Release();
  372.     DecrementSocketsClientCount();
  373. }
  374.     }
  375.     CheckClients();
  376. exit:
  377.     return theErr;
  378. }
  379. LRESULT
  380. CAsyncNetThread::OnAsyncDNS(WPARAM wParam, LPARAM lParam)
  381. {
  382. //    m_pThreadEngineMutex->Lock();
  383.     void* pVoid = 0;
  384.     if (!m_ClientSocketsMap ||
  385. !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
  386.     {
  387. // m_pThreadEngineMutex->Unlock();
  388.      return TRUE;
  389.     }
  390.     ThreadedConn* pConnection = (ThreadedConn*) pVoid;
  391.     pConnection->OnAsyncDNS((BOOL) lParam);
  392.     
  393. //    m_pThreadEngineMutex->Unlock();
  394.     return TRUE;
  395. }
  396. LRESULT
  397. CAsyncNetThread::OnAsyncConnect(WPARAM wParam, LPARAM lParam)
  398. {
  399. //    m_pThreadEngineMutex->Lock();
  400.     void* pVoid = 0;
  401.     if (!m_ClientSocketsMap ||
  402. !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
  403.     {
  404. // m_pThreadEngineMutex->Unlock();
  405. return TRUE;
  406.     }
  407.     ThreadedConn* pConnection = (ThreadedConn*) pVoid;
  408.     pConnection->OnConnect((BOOL) lParam);
  409.     
  410. //    m_pThreadEngineMutex->Unlock();
  411.     return TRUE;
  412. }
  413. LRESULT
  414. CAsyncNetThread::OnAsyncRead(WPARAM wParam, LPARAM lParam)
  415. {
  416. //    m_pThreadEngineMutex->Lock();
  417.     void* pVoid = 0;
  418.     if (!m_ClientSocketsMap ||
  419. !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
  420.     {
  421. // m_pThreadEngineMutex->Unlock();
  422. return TRUE;
  423.     }
  424.     ThreadedConn* pConnection = (ThreadedConn*) pVoid;
  425.     pConnection->OnReadNotification();
  426.     
  427. //    m_pThreadEngineMutex->Unlock();
  428.     return TRUE;
  429. }
  430. LRESULT
  431. CAsyncNetThread::OnAsyncWrite(WPARAM wParam, LPARAM lParam)
  432. {
  433. //    m_pThreadEngineMutex->Lock();
  434.     void* pVoid = 0;
  435.     if (!m_ClientSocketsMap ||
  436. !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
  437.     {
  438. // m_pThreadEngineMutex->Unlock();
  439. return TRUE;
  440.     }
  441.     ThreadedConn* pConnection = (ThreadedConn*) pVoid;
  442.     pConnection->OnWriteNotification();
  443.     
  444. //    m_pThreadEngineMutex->Unlock();
  445.     return TRUE;
  446. }
  447. LRESULT
  448. CAsyncNetThread::OnAsyncAccept(WPARAM wParam, LPARAM lParam)
  449. {
  450. //    m_pThreadEngineMutex->Lock();
  451.     void* pVoid = 0;
  452.     if (!m_ClientSocketsMap ||
  453. !m_ClientSocketsMap->Lookup((void*) wParam, pVoid))
  454.     {
  455. // m_pThreadEngineMutex->Unlock();
  456. return TRUE;
  457.     }
  458.     ThreadedConn* pConnection = (ThreadedConn*) pVoid;
  459.     pConnection->OnAcceptNotification();
  460.     
  461. //    m_pThreadEngineMutex->Unlock();
  462.     return TRUE;
  463. }