casynthr.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:14k
源码类别:

Symbian

开发平台:

Visual C++

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