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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: threngin.cpp,v 1.4.2.3 2004/07/09 01:47:02 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 <stdio.h>
  50. #include "hxresult.h"
  51. #include "hxassert.h"
  52. #include "hxmap.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 "hxtick.h"
  60. #if defined(_UNIX) && (defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED))
  61. #include "platform/unix/UnixThreads.h"
  62. #include "platform/unix/unix_net.h"
  63. #endif
  64. #if defined(_MACINTOSH) && defined(_CARBON) && defined(THREADS_SUPPORTED)
  65. #include "carbthrd.h"
  66. #endif
  67. #include "hxheap.h"
  68. #ifdef _DEBUG
  69. #undef HX_THIS_FILE
  70. static const char HX_THIS_FILE[] = __FILE__;
  71. #endif  
  72. #define ALLFS     0xFFFFFFFF
  73. #define LOCAL_LOOPBACK_ADDR 0x7F000001 // 127.0.0.1
  74. #define LOCAL_LOOPBACK_NAME "127.0.0.1"
  75. #define LOCAL_LOOPBACK_PORT 0x1234
  76. void* NetworkThreadMainLoop(void* pArg);
  77. ThreadEngine*   ThreadEngine::m_pzThreadEngine = NULL;
  78. /* Global destructor will be called at DLL shutdown and thread engine
  79.  * will be destroyed
  80.  */ 
  81. DestructEngine selfDestructor;
  82. ThreadEngine*    
  83. ThreadEngine::GetThreadEngine(void)
  84. {
  85.     if (!m_pzThreadEngine)
  86.     {
  87. m_pzThreadEngine = new ThreadEngine; 
  88.     }
  89.     return m_pzThreadEngine;
  90. }
  91. ThreadEngine::ThreadEngine()
  92.     : m_pNetworkThread(0)
  93.     , m_pMainAppThread(0)
  94.     , m_pMutex(0)
  95.     , m_pSockMap(0)
  96.     , m_pQuitEvent(NULL)
  97.     , m_bInDestructor(FALSE)
  98. #if defined(_MACINTOSH) && defined(_CARBON) && defined(THREADS_SUPPORTED)
  99.     , m_ThreadedNetworkingCarbonTimerUPP(NULL)
  100.     , m_ThreadedNetworkingCarbonTimerRef(NULL)
  101. #endif
  102. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  103.     , m_pLocalListener(NULL)
  104.     , m_pLocalReader(NULL)
  105.     , m_pLocalWriter(NULL)
  106. #endif // HELIX_FEATURE_NETWORK_USE_SELECT
  107. {
  108.     m_pzThreadEngine = this;
  109. #if defined( THREADS_SUPPORTED ) || defined( _UNIX_THREADED_NETWORK_IO )
  110.     HXMutex::MakeMutex(m_pMutex);
  111.     HXThread::MakeThread(m_pNetworkThread);
  112.     HXEvent::MakeEvent(m_pQuitEvent, NULL);
  113. #else
  114.     HXMutex::MakeStubMutex(m_pMutex);
  115.     HXThread::MakeStubThread(m_pNetworkThread);
  116.     HXEvent::MakeStubEvent(m_pQuitEvent, NULL);
  117. #endif
  118.     m_pNetworkThread->CreateThread(NetworkThreadMainLoop, (void*) this);
  119.     m_pSockMap = new CHXMapPtrToPtr;
  120.     
  121.     /* This is just a wrapper thread for the main application 
  122.      * It is really a hack. Will do it the right way sometime soon*/
  123. #if defined( THREADS_SUPPORTED ) || defined( _UNIX_THREADED_NETWORK_IO )
  124.     HXThread::MakeThread(m_pMainAppThread);
  125. #else
  126.     HXThread::MakeStubThread(m_pMainAppThread);
  127. #endif
  128.     m_pMainAppThread->YieldTimeSlice();
  129. #if defined(_MACINTOSH) && defined(_CARBON) && defined(THREADS_SUPPORTED)
  130.     HX_ASSERT(!m_ThreadedNetworkingCarbonTimerUPP);
  131.     HX_ASSERT(!m_ThreadedNetworkingCarbonTimerRef);
  132.     m_ThreadedNetworkingCarbonTimerUPP = ::NewEventLoopTimerUPP(
  133. (EventLoopTimerProcPtr)FauxMainAppCarbonTimer);
  134.     InstallEventLoopTimer(GetCurrentEventLoop(), 0, 50 * kEventDurationMillisecond,
  135. m_ThreadedNetworkingCarbonTimerUPP, this, &m_ThreadedNetworkingCarbonTimerRef);
  136. #endif
  137. }
  138. ThreadEngine::~ThreadEngine()
  139. {
  140.     m_pMutex->Lock();
  141.     m_bInDestructor = TRUE;
  142.     if (m_pSockMap && m_pSockMap->GetCount() > 0)
  143.     {
  144. CHXMapPtrToPtr::Iterator ndxConn = m_pSockMap->Begin();
  145. for (; ndxConn != m_pSockMap->End(); ++ndxConn)
  146. {
  147.     ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
  148.     pConn->AddRef();
  149. }
  150.     }
  151.     m_pMutex->Unlock();
  152.     if (m_pSockMap)
  153.     {
  154. //HX_ASSERT(m_pSockMap->GetCount() == 0);
  155. if (m_pSockMap->GetCount() > 0)
  156. {
  157.     CHXMapPtrToPtr::Iterator ndxConn = m_pSockMap->Begin();
  158.     for (; ndxConn != m_pSockMap->End(); ++ndxConn)
  159.     {
  160. ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
  161. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  162. if (pConn == m_pLocalReader ||
  163.     pConn == m_pLocalWriter ||
  164.     pConn == m_pLocalListener)
  165.     continue;
  166. #endif // HELIX_FEATURE_NETWORK_USE_SELECT
  167. pConn->finaldone();
  168. pConn->Release();
  169.     }
  170. }   
  171.     }
  172.     if (m_pNetworkThread)
  173.     {
  174. HXThreadMessage msg(HXMSG_QUIT, NULL, NULL);
  175. if (m_pNetworkThread->PostMessage(&msg) == HXR_OK)
  176. {
  177.       m_pQuitEvent->Wait(ALLFS);
  178. }
  179.         
  180. m_pNetworkThread->Exit(0);
  181. delete m_pNetworkThread;
  182. m_pNetworkThread = 0;
  183.     }
  184. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  185.     m_pLocalReader->Release();
  186.     m_pLocalWriter->Release();
  187.     m_pLocalListener->Release();
  188. #endif // HELIX_FEATURE_NETWORK_USE_SELECT
  189. #if defined(_MACINTOSH) && defined(_CARBON) && defined(THREADS_SUPPORTED)
  190.     ::RemoveEventLoopTimer(m_ThreadedNetworkingCarbonTimerRef);
  191.     m_ThreadedNetworkingCarbonTimerRef;
  192.     
  193.     ::DisposeEventLoopTimerUPP(m_ThreadedNetworkingCarbonTimerUPP);
  194.     m_ThreadedNetworkingCarbonTimerUPP;
  195. #endif
  196.     if (m_pMainAppThread)
  197.     {
  198. delete m_pMainAppThread;
  199. m_pMainAppThread = 0;
  200.     }
  201.     if (m_pMutex)
  202.     {
  203. delete m_pMutex;
  204. m_pMutex = 0;
  205.     }
  206.     if (m_pQuitEvent)
  207.     {
  208. delete m_pQuitEvent;
  209. m_pQuitEvent = 0;
  210.     }
  211.     if (m_pSockMap)
  212.     {
  213. m_pSockMap->RemoveAll();
  214. delete m_pSockMap;
  215. m_pSockMap = 0;
  216.     }
  217. }
  218. void 
  219. ThreadEngine::DestroyThreadEngine(void)
  220. {
  221.     if (m_pzThreadEngine)
  222.     {
  223. ThreadEngine* pThreadEngine = m_pzThreadEngine;
  224. m_pzThreadEngine = NULL;
  225. delete pThreadEngine;
  226.     }
  227. }
  228. HX_RESULT
  229. ThreadEngine::AttachSocket(ThreadedConn* pConn)
  230. {
  231.     void* pVoid = 0;
  232.     HX_RESULT theErr = HXR_OK;
  233.     m_pMutex->Lock();
  234.     if (m_pSockMap->Lookup(pConn, pVoid))
  235.     {
  236. theErr = HXR_FAIL;
  237.     }
  238.     else
  239.     {
  240. pConn->AddRef();
  241. m_pSockMap->SetAt((void*) pConn, (void*) pConn);
  242.     }
  243.     if (m_pSockMap->GetCount() == 1)
  244.     {
  245. #ifdef WIN32_PLATFORM_PSPC
  246. HXThreadMessage msg(HXMSG_ASYNC_RESUME, (void*) 200, NULL);
  247. #else
  248. HXThreadMessage msg(HXMSG_ASYNC_RESUME, (void*) 20, NULL);
  249. #endif
  250. m_pNetworkThread->PostMessage(&msg);
  251.     }
  252.     m_pMutex->Unlock();
  253.     return theErr;
  254. }
  255. HX_RESULT
  256. ThreadEngine::DetachSocket(ThreadedConn* pConn)
  257. {
  258.     void* pVoid = 0;
  259.     HX_RESULT theErr = HXR_OK;
  260.     m_pMutex->Lock();
  261.     void* blah;
  262.     if (!m_pSockMap->Lookup((void*) pConn, (void*&) blah))
  263.     {
  264. theErr = HXR_FAIL;
  265.     }
  266.     else
  267.     {
  268. /* if we are in the destructor, no need to remove from the map */
  269. if (!m_bInDestructor)
  270. {
  271.     m_pSockMap->RemoveKey((void*) pConn);
  272. }
  273. pConn->Detached();
  274. pConn->Release();
  275.     }
  276.     if (m_pSockMap->GetCount() == 0)
  277.     {
  278. HXThreadMessage msg(HXMSG_ASYNC_STOP, NULL, NULL);
  279. m_pNetworkThread->PostMessage(&msg);
  280.     }
  281.     m_pMutex->Unlock();
  282.     return theErr;
  283. }
  284. //-----------------------------------------------------------
  285. void
  286. ThreadEngine::DoAsyncCallback(ThreadedConn* pConn, IHXCallback* pCallback)
  287. {
  288.     void* pVoid = 0;
  289.     m_pMutex->Lock();
  290.     /* Fire callback ONLY if the connected socket is still active*/
  291.     if (m_pSockMap->Lookup(pConn, pVoid))
  292.     {
  293. pCallback->Func();
  294.     }
  295.     pCallback->Release();
  296.     m_pMutex->Unlock();
  297. }
  298. //-----------------------------------------------------------
  299. void
  300. ThreadEngine::DoNetworkIO(ThreadedConn* pConn)
  301. {
  302.     CHXMapPtrToPtr::Iterator ndxConn;
  303.     m_pMutex->Lock();
  304.     if (m_bInDestructor)
  305.     {
  306. goto exit;
  307.     }
  308.     if (pConn)
  309.     {
  310. void* pVoid = 0;
  311. if (m_pSockMap->Lookup(pConn, pVoid))
  312. {
  313.     pConn->DoNetworkIO();
  314. }
  315. goto exit;
  316.     }
  317.     ndxConn = m_pSockMap->Begin();
  318.     for (; ndxConn != m_pSockMap->End(); ++ndxConn)
  319.     {
  320. ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
  321. pConn->DoNetworkIO();
  322.     }
  323. exit:
  324.     m_pMutex->Unlock();
  325. }
  326. //-----------------------------------------------------------
  327. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  328. HX_RESULT 
  329. ThreadEngine::WaitforSelect()
  330. {
  331.     HX_RESULT theErr = HXR_FAIL;
  332.     ThreadedConn *pConn = NULL;
  333.     if (m_bInDestructor)
  334. pConn = m_pLocalReader;
  335.     if (m_pLocalReader && m_pLocalReader->GetActualConn())
  336. theErr = m_pLocalReader->GetActualConn()->WaitforSelect(this,pConn);
  337.     return theErr;
  338. }
  339. #endif // HELIX_FEATURE_NETWORK_USE_SELECT
  340. //-----------------------------------------------------------
  341. void*
  342. NetworkThreadMainLoop(void* pArg)
  343. {
  344.     ThreadEngine*   pEngine = (ThreadEngine*) pArg;
  345.     HXMutex*     pMutex  = pEngine->m_pMutex; 
  346.     HXThread*     pThread = pEngine->m_pNetworkThread;
  347.     HXThreadMessage msg;
  348.     BOOL     bDone   = FALSE;
  349.     UINT32     ulSleepTime = 0;
  350.     ULONG32     ulLastTimerCallback = HX_GET_TICKCOUNT();
  351.     
  352. #if defined( _WIN32 ) || defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED)
  353.     UINT32  ulTimerId = 0;
  354. #endif /*_WIN32 || _UNIX_THREADED_NETWORK_IO */
  355.     
  356. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  357.     unsigned short iSize;
  358.     HX_RESULT theErr = HXR_FAIL;
  359.     UINT32 ulPlatformData = 0;
  360.     BOOL bRWStartup = FALSE;
  361.     BOOL bMoreToRead = FALSE;
  362.     BOOL bDebug = FALSE;
  363.     pEngine->m_pLocalListener  = new ThreadedConn(HX_TCP_SOCKET);
  364.     pEngine->m_pLocalWriter  = new ThreadedConn(HX_TCP_SOCKET);
  365.     pEngine->m_pLocalReader  = NULL;
  366.     pThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
  367. //    pThread->SetPriority(THREAD_PRIORITY_HIGHEST);
  368. #if defined (_WIN32)
  369.     ulPlatformData = (UINT32)GetModuleHandle(NULL);
  370. #elif defined (_WIN16)
  371.     ulPlatformData = (UINT32)(int)g_hInstance;
  372. #endif
  373.     if (pEngine->m_pLocalListener && pEngine->m_pLocalWriter)
  374. theErr = pEngine->m_pLocalListener->listen(
  375.     LOCAL_LOOPBACK_ADDR
  376.     , LOCAL_LOOPBACK_PORT
  377.     , 4 // backlog
  378.     , 0 // blocking
  379.     , ulPlatformData // ulPlatform
  380.     );
  381.     if (SUCCEEDED(theErr))
  382.     // writer connects and reader accepts
  383. theErr = pEngine->m_pLocalWriter->connect(
  384.     LOCAL_LOOPBACK_NAME
  385.     , LOCAL_LOOPBACK_PORT
  386.     , 0 // blocking
  387.     , ulPlatformData // ulPlatform
  388.     );
  389.     if (SUCCEEDED(theErr) && !bDebug)
  390.     // writer connects and reader accepts
  391. theErr = pEngine->m_pLocalListener->accept(LOCAL_LOOPBACK_ADDR);
  392.     if (FAILED(theErr))
  393.     {
  394. if (pEngine->m_pLocalListener)
  395. {
  396.     pEngine->DetachSocket(pEngine->m_pLocalListener);
  397.     pEngine->m_pLocalListener = NULL;
  398. }
  399. if (pEngine->m_pLocalWriter)
  400. {
  401.     pEngine->DetachSocket(pEngine->m_pLocalWriter);
  402.     pEngine->m_pLocalWriter = NULL;
  403. }
  404. if (pEngine->m_pLocalReader)
  405. {
  406.     pEngine->DetachSocket(pEngine->m_pLocalReader);
  407.     pEngine->m_pLocalReader = NULL;
  408. }
  409.     }
  410.     while (!bDone)
  411.     {
  412. if (bDebug || FAILED(theErr) 
  413.     || !pEngine->m_pLocalWriter 
  414.     || !pEngine->m_pLocalReader 
  415.     || !pEngine->m_pLocalWriter->connection_really_open()
  416.     || !pEngine->m_pLocalReader->connection_really_open()
  417.     )
  418. { // process connect and accept messages, then use select
  419.     pEngine->m_pNetworkThread->m_bUseReaderWriter = FALSE;
  420.            if (ulTimerId <= 0)
  421.            {
  422.                ulSleepTime = 20;
  423.                ulTimerId = HXAsyncTimer::SetTimer( ulSleepTime, pThread );
  424.            }
  425.     if (pThread->GetMessage(&msg, 0, 0) != HXR_OK)
  426. break;
  427. }
  428. else
  429. {
  430.     if (!pEngine->m_pNetworkThread->m_bUseReaderWriter || bRWStartup)
  431.     { // process messages in queue
  432. if (!bRWStartup)
  433. {
  434.     if (ulTimerId > 0)
  435.     {
  436.        HXAsyncTimer::KillTimer(ulTimerId);
  437.        ulTimerId = 0;
  438.     }
  439.     msg.m_ulMessage = HXMSG_ASYNC_START_READERWRITER;
  440.     theErr = pEngine->m_pNetworkThread->PostMessage(&msg);
  441. }
  442. pEngine->m_pNetworkThread->m_bUseReaderWriter = TRUE;
  443. pEngine->m_pLocalWriter->set_callback(pEngine->m_pLocalWriter->get_callback()); // for post network msg
  444. pThread->SetNetworkMessageConnection(pEngine->m_pLocalWriter);
  445. bRWStartup = TRUE;
  446. if (pThread->GetMessage(&msg, 0, 0) != HXR_OK)
  447.     break;
  448.     }
  449.     else
  450.     {
  451. if (!bMoreToRead)
  452. {
  453.     if (HXR_FAIL == pEngine->WaitforSelect())
  454. break;
  455. }
  456. msg.m_ulMessage = 0;
  457. iSize = sizeof(HXThreadMessage);
  458. pEngine->m_pLocalReader->m_bNetworkIOPending = TRUE;
  459. theErr = pEngine->m_pLocalReader->read(&msg,&iSize);
  460. if (HXR_OK != theErr)
  461. {
  462.     if (HXR_WOULD_BLOCK == theErr)
  463.     {
  464. bMoreToRead = FALSE;
  465. theErr = HXR_OK;
  466. continue;
  467.     }
  468.     // reader failed, must be disconnected, return to msg loop
  469.     break;
  470. }
  471. if (iSize != sizeof(HXThreadMessage)) // fixme
  472. {
  473.     bMoreToRead = FALSE;
  474.     continue;
  475. }
  476. else
  477.     bMoreToRead = TRUE;
  478.     }
  479. }
  480. #else
  481.     while (!bDone && pThread->GetMessage(&msg, 0, 0) == HXR_OK)
  482.     {
  483. #endif // HELIX_FEATURE_NETWORK_USE_SELECT
  484. switch (msg.m_ulMessage)
  485. {
  486. #if defined( _WIN32 ) || defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED)
  487.            case HXMSG_ASYNC_TIMER: //Look in hxmsgs.h (WM_TIMER under win32)
  488.            {
  489. #if defined(_UNIX_THREADED_NETWORK_IO) || (defined(THREADS_SUPPORTED) && defined(_UNIX))
  490.                unix_TCP::process_idle();
  491. #endif                    
  492.                ULONG32 ulCurrentTime = HX_GET_TICKCOUNT();
  493.                
  494.                if (CALCULATE_ELAPSED_TICKS(ulLastTimerCallback, 
  495.                                            ulCurrentTime) >= ulSleepTime)
  496.                {
  497.                    ulLastTimerCallback = ulCurrentTime;
  498.                    pEngine->DoNetworkIO(); 
  499.                }
  500.            }
  501.            break;
  502. #endif /* _WIN32 || _UNIX_THREADED_NETWORK_IO */
  503.            case HXMSG_ASYNC_NETWORKIO:
  504.            {
  505.                ThreadedConn* pConn = (ThreadedConn*) msg.m_pParam1; 
  506.                pEngine->DoNetworkIO(pConn);
  507.            }
  508.            break;
  509.            case HXMSG_ASYNC_CALLBACK:
  510.            {
  511.                ThreadedConn* pConn = (ThreadedConn*) msg.m_pParam1; 
  512.                IHXCallback* pCallback = (IHXCallback*) msg.m_pParam2;
  513.                pEngine->DoAsyncCallback(pConn, pCallback);
  514.            }
  515.            break;
  516. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  517.            case HXMSG_ASYNC_SETREADER_CONNECTION:
  518.            {
  519.                pEngine->m_pLocalReader = (ThreadedConn*) msg.m_pParam2; 
  520.            }
  521.            break;
  522.            case HXMSG_ASYNC_START_READERWRITER:
  523.            {
  524. pEngine->m_pNetworkThread->m_bUseReaderWriter = TRUE;
  525. bRWStartup = FALSE;
  526.            }
  527.            break;
  528. #endif //HELIX_FEATURE_NETWORK_USE_SELECT
  529.            case HXMSG_ASYNC_DETACH:
  530.            {
  531.                ThreadedConn* pConn = (ThreadedConn*) msg.m_pParam1; 
  532.                pEngine->DetachSocket(pConn); 
  533.            }
  534.            break;
  535.            case HXMSG_QUIT:
  536.            {
  537.                bDone = TRUE;
  538.            }
  539.            
  540.            break;
  541.            case HXMSG_ASYNC_RESUME:
  542. #if defined( _WIN32 ) || defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED)
  543.            {
  544.                if (ulTimerId > 0)
  545.                {
  546.                    HXAsyncTimer::KillTimer(ulTimerId);
  547.                    ulTimerId = 0;
  548.                }
  549.                
  550.                ulSleepTime = (UINT32)(PTR_INT)msg.m_pParam1;
  551.                ulTimerId = HXAsyncTimer::SetTimer( ulSleepTime, pThread );
  552.            }
  553. #endif /* _WIN32 || _UNIX_THREADED_NETWORK_IO */
  554.            break;
  555.            
  556.            case HXMSG_ASYNC_STOP:
  557. #if defined( _WIN32 ) || defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED)
  558.            {
  559.                if (ulTimerId > 0)
  560.                {
  561.                    HXAsyncTimer::KillTimer( ulTimerId );
  562.                    ulTimerId   = 0;
  563.                    ulSleepTime = 0;
  564.                }
  565.            }
  566. #endif /* _WIN32 || _UNIX_THREADED_NETWORK_IO */
  567.            break;
  568.            default:
  569.                pThread->DispatchMessage(&msg);
  570.                break;
  571. }
  572.     }
  573.     
  574. #if defined( _WIN32 ) || defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED)
  575.     if (ulTimerId > 0)
  576.     {
  577.         HXAsyncTimer::KillTimer( ulTimerId );
  578.     }
  579. #endif /* _WIN32 || _UNIX_THREADED_NETWORK_IO */
  580.     
  581.     pEngine->m_pQuitEvent->SignalEvent();
  582.     
  583.     return (void*) 0;
  584. }
  585. #if defined(_MACINTOSH) && defined(_CARBON) && defined(THREADS_SUPPORTED)
  586. void ThreadEngine::FauxMainAppCarbonTimer(EventLoopTimerRef, void* /* unused */)
  587. {
  588.     // xxxbobclark this is essentially just ripped off from Greg Wright's
  589.     // similar message handling loop for Unix.
  590.     //
  591.     // It's been moved to pnio because more places than just rmacore
  592.     // (i.e. rmacleng) use the threaded implementation of networking,
  593.     // viz. rnqueue for Auto-Update. Using a Carbon Timer to get time
  594.     // periodically can luckily be implemented in pnio; it's sure to
  595.     // get actual System Time.
  596.     
  597.     ThreadEngine* pEngine = ThreadEngine::GetThreadEngine();
  598.     HX_ASSERT(pEngine);
  599.     HXCarbonThread* pMainAppThread = (HXCarbonThread*)pEngine->GetMainAppThread();
  600.     HX_ASSERT(pMainAppThread);
  601.     HXThreadMessage msg;
  602.     
  603.     while (pMainAppThread->PeekMessage(&msg, 0, 0, TRUE) == HXR_OK)
  604.     {
  605. if (msg.m_ulMessage != 0)
  606. {
  607.     ThreadedConn* pThreadedConn = (ThreadedConn*)msg.m_pParam1;
  608.     if (pThreadedConn)
  609.     {
  610. switch (msg.m_ulMessage)
  611. {
  612.     case HXMSG_ASYNC_DNS:
  613. pThreadedConn->OnAsyncDNS((BOOL)msg.m_pParam2);
  614. break;
  615.     case HXMSG_ASYNC_CONNECT:
  616. pThreadedConn->OnConnect((BOOL)msg.m_pParam2);
  617. break;
  618.     case HXMSG_ASYNC_READ:
  619. pThreadedConn->OnReadNotification();
  620. break;
  621.     case HXMSG_ASYNC_WRITE:
  622. pThreadedConn->OnWriteNotification();
  623. break;
  624.     case HXMSG_ASYNC_ACCEPT:
  625. pThreadedConn->OnAcceptNotification();
  626. break;
  627.     default:
  628. HX_ASSERT(!"Unknown message in threaded networking Carbon Timer");
  629. break;
  630. }
  631.     }
  632. }
  633.     }
  634. }
  635. #endif