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

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. //This is used to turn off threads in libc5 builds.
  36. #ifdef _UNIX_THREADS_SUPPORTED
  37. #include <errno.h>
  38. #include "hxtypes.h"
  39. #include "hxresult.h"
  40. #include <pthread.h>
  41. #include <sys/time.h>
  42. #include <semaphore.h>
  43. #include "pthreadthreads.h"
  44. //=======================================================================
  45. //
  46. //                      HXPthreadThread
  47. //                   ----------------------
  48. //
  49. //=======================================================================
  50. HXPthreadThread::HXPthreadThread()
  51.     : HXUnixThread()
  52. {}
  53. HXPthreadThread::~HXPthreadThread()
  54. {}
  55. HX_RESULT HXPthreadThread::_thread_create( ULONG32& ulThreadID, void*(pfExecFunc(void*)), void* pArg )
  56. {
  57.     HX_RESULT retVal = HXR_OK;
  58.     pthread_t threadID=0;
  59.     int nCode = pthread_create( &threadID, NULL, pfExecFunc, pArg );
  60.     ulThreadID = threadID;
  61.     if(nCode!=0)
  62.     {
  63.         ulThreadID = 0;
  64.         retVal = HXR_FAIL;
  65.         HX_ASSERT( "Failed to create thread"==NULL );
  66.     }
  67.     return retVal;
  68. }
  69. ULONG32 HXPthreadThread::_thread_self()
  70. {
  71.     return pthread_self();
  72. }
  73. void HXPthreadThread::_thread_exit(UINT32 unExitCode)
  74. {
  75.     pthread_exit( (void*)unExitCode );
  76. }
  77. void HXPthreadThread::_thread_cancel(ULONG32 ulThreadID)
  78. {
  79.     pthread_cancel( ulThreadID );
  80. }
  81. ULONG32 HXPthreadThread::_thread_join(ULONG32 ulThreadID)
  82. {
  83.     void* pvRetVal = NULL;
  84.     pthread_join( ulThreadID, &pvRetVal );
  85.     return (ULONG32)(PTR_INT)pvRetVal;
  86. }
  87. //=======================================================================
  88. //
  89. //                      HXPthreadMutex
  90. //                   ------------------
  91. //
  92. //=======================================================================
  93. HXPthreadMutex::HXPthreadMutex()
  94.     : HXUnixMutex(),
  95.       m_ulOwnerThread(0),
  96.       m_ulLockCount(0)
  97. {
  98.      memset(&m_mutex,       0, sizeof(m_mutex));
  99.      memset(&m_mtxLockLock, 0, sizeof(m_mtxLockLock));
  100. #ifdef _TIMEDWAITS_RECURSIVE_MUTEXES
  101.      pthread_mutexattr_t attr;
  102.      pthread_mutexattr_init( &attr );
  103. #ifdef PTHREAD_MUTEX_RECURSIVE_NP
  104.      pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
  105. #else
  106.      pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
  107. #endif
  108.      pthread_mutex_init( &m_mutex, &attr );
  109.      pthread_mutexattr_destroy( &attr );
  110. #else     
  111.      pthread_mutex_init( &m_mutex,NULL);
  112.      pthread_mutex_init( &m_mtxLockLock, NULL );
  113. #endif     
  114. }
  115.     
  116. HXPthreadMutex::~HXPthreadMutex()
  117. {
  118.     pthread_mutex_destroy( &m_mutex );
  119. #ifndef _TIMEDWAITS_RECURSIVE_MUTEXES    
  120.     m_ulLockCount   = 0;
  121.     m_ulOwnerThread = 0;
  122.     pthread_mutex_destroy( &m_mtxLockLock );
  123. #endif    
  124. }
  125.     
  126. HX_RESULT HXPthreadMutex::_Lock()
  127. {
  128.     //We simulate recursive mutexes.
  129.     HX_RESULT res     = HXR_OK;
  130.     int       nResult = 0;
  131. #ifndef _TIMEDWAITS_RECURSIVE_MUTEXES    
  132.     nResult = pthread_mutex_lock(&m_mtxLockLock);
  133.     if (nResult != 0 )
  134.     {
  135.         res = HXR_FAIL;
  136.         return res;
  137.     }
  138.         
  139.     if( m_ulOwnerThread != pthread_self() )
  140.     {
  141.         pthread_mutex_unlock(&m_mtxLockLock);        
  142.         //We are going to block for sure.
  143.         nResult = pthread_mutex_lock(&m_mutex);
  144.         //Take ownership.
  145.         if ( pthread_mutex_lock(&m_mtxLockLock) != 0 )
  146.         {
  147.             //This should not happen but if does then unlock the
  148.             //main mutex and return failure.
  149.             if ( nResult == 0 )
  150.             {
  151.                 pthread_mutex_unlock(&m_mutex);
  152.             } 
  153.             return HXR_FAIL;
  154.         }
  155.                 
  156.         if ( nResult == 0 )
  157.         {
  158.              m_ulOwnerThread = pthread_self();
  159.              m_ulLockCount   = 1;
  160.         }
  161.         else
  162.         {
  163.             res = HXR_FAIL;
  164.         }
  165.     }
  166.     else
  167.     {
  168.         //We alread have it locked. Just increment the lock count
  169.         m_ulLockCount++;
  170.     }
  171.     pthread_mutex_unlock(&m_mtxLockLock);
  172. #else
  173.     pthread_mutex_lock(&m_mutex);
  174. #endif    
  175.     return res;
  176. }
  177.     
  178. HX_RESULT HXPthreadMutex::_Unlock()
  179. {
  180.     HX_RESULT res     = HXR_OK;
  181.     int       nResult = 0;
  182. #ifndef _TIMEDWAITS_RECURSIVE_MUTEXES    
  183.     nResult = pthread_mutex_lock(&m_mtxLockLock);
  184.     if ( nResult != 0 )
  185.     {
  186.         res = HXR_FAIL;
  187.         return res;
  188.     }
  189.     
  190.     //Sanity checks.
  191.     HX_ASSERT( m_ulLockCount != 0 && m_ulOwnerThread == pthread_self() );
  192.     if( m_ulLockCount == 0 || m_ulOwnerThread!=pthread_self() )
  193.     {
  194.         pthread_mutex_unlock(&m_mtxLockLock);  
  195.         return HXR_FAIL;
  196.     }
  197.     
  198.     
  199.     if( m_ulLockCount == 1 )
  200.     {
  201.         //We are really done with it. Do the real unlock now.
  202.         nResult = pthread_mutex_unlock(&m_mutex);
  203.         if ( nResult == 0 )
  204.         {
  205.             m_ulOwnerThread = 0;
  206.             m_ulLockCount=0;
  207.         }
  208.         else
  209.         {
  210.             res = HXR_FAIL;
  211.         }
  212.     }
  213.     else
  214.     {
  215.         m_ulLockCount--;
  216.     }
  217.     pthread_mutex_unlock(&m_mtxLockLock);
  218. #else
  219.     pthread_mutex_unlock(&m_mutex);
  220. #endif    
  221.     return res;
  222. }
  223.     
  224. HX_RESULT HXPthreadMutex::_TryLock()
  225. {
  226.     HX_RESULT res = HXR_OK;    
  227.     int       nResult = 0;
  228. #ifndef _TIMEDWAITS_RECURSIVE_MUTEXES    
  229.     nResult = pthread_mutex_lock(&m_mtxLockLock);
  230.     if (nResult != 0 )
  231.     {
  232.         res = HXR_FAIL;
  233.         return res;
  234.     }
  235.     
  236.     if( m_ulOwnerThread != pthread_self() )
  237.     {
  238.         nResult = pthread_mutex_trylock(&m_mutex);
  239.                 
  240.         if ( nResult == 0 )
  241.         {
  242.             m_ulOwnerThread = pthread_self();
  243.             m_ulLockCount   = 1;
  244.         }
  245.         else
  246.         {
  247.             res = HXR_FAIL;
  248.         }
  249.     }
  250.     else
  251.     {
  252.         //We alread have it locked. Just increment the lock count
  253.         m_ulLockCount++;
  254.     }
  255.     pthread_mutex_unlock(&m_mtxLockLock);
  256. #else
  257.     nResult = pthread_mutex_trylock(&m_mutex);
  258.     if ( nResult != 0 )
  259.     {
  260.         res = HXR_FAIL;
  261.     }
  262. #endif    
  263.     return res;
  264. }
  265. pthread_mutex_t* HXPthreadMutex::_GetPthreadMutex()
  266. {
  267.     return &m_mutex; 
  268. }
  269. //=======================================================================
  270. //
  271. //                   HXPthreadCondition
  272. //                   ----------------------
  273. //
  274. //=======================================================================
  275. HXPthreadCondition::HXPthreadCondition(HXUnixMutex*& pMutex)
  276. {
  277.     HX_ASSERT( pMutex == NULL );
  278.     //Create the mutex we need to associate with this cond.
  279.     
  280.     m_pMutex = new HXPthreadMutex();
  281.     pMutex = (HXUnixMutex*)m_pMutex;
  282.     //Init our cond var.
  283.     pthread_cond_init( &m_cond, NULL );
  284. }
  285. HXPthreadCondition::~HXPthreadCondition()
  286. {
  287.     pthread_cond_destroy(&m_cond);
  288.     HX_DELETE( m_pMutex );
  289. }
  290. HX_RESULT HXPthreadCondition::_Signal()
  291. {
  292.     pthread_cond_signal(&m_cond);
  293.     return HXR_OK;
  294. }
  295. HX_RESULT HXPthreadCondition::_Broadcast()
  296. {
  297.     pthread_cond_broadcast(&m_cond);
  298.     return HXR_OK;
  299. }
  300. HX_RESULT HXPthreadCondition::_Wait()
  301. {
  302.     HX_ASSERT( m_pMutex );
  303.     //m_pMuex MUST BE LOCKED ALL READY!
  304.     pthread_cond_wait(&m_cond, m_pMutex->_GetPthreadMutex());
  305.     return HXR_OK;
  306. }
  307. HX_RESULT HXPthreadCondition::_TimedWait(UINT32 unTimeOut)
  308. {
  309.     //m_pMuex MUST BE LOCKED ALL READY!
  310.     HX_RESULT       ret = HXR_OK;
  311.     struct timeval  now;
  312.     struct timespec timeout;
  313.     int             retcode;
  314.     gettimeofday(&now, NULL);
  315.     long int waitSeconds = unTimeOut/1000;
  316.     long int nanoSeconds = (unTimeOut-(waitSeconds*1000))*1000000;
  317.     timeout.tv_sec  = now.tv_sec+waitSeconds;
  318.     timeout.tv_nsec = now.tv_usec*1000+nanoSeconds;
  319.     if( timeout.tv_nsec >= 1000000000 )
  320.     {
  321.         timeout.tv_nsec -= 1000000000;
  322.         timeout.tv_sec  += 1;
  323.     }
  324.     retcode = pthread_cond_timedwait(&m_cond, m_pMutex->_GetPthreadMutex(), &timeout);
  325.     
  326.     if(retcode==-1)
  327.     {
  328.         ret = HXR_FAIL;
  329.         //We really could use a HXR_TIMEDOUT.
  330.         if( errno == ETIMEDOUT )
  331.             ret = HXR_WOULD_BLOCK;
  332.     }
  333.     return ret;
  334. }
  335. #ifndef _MAC_UNIX
  336. //=======================================================================
  337. //
  338. //                      HXPthreadSemaphore
  339. //                   ------------------
  340. //
  341. //=======================================================================
  342. HXPthreadSemaphore::HXPthreadSemaphore(UINT32 unInitialCount)
  343.     : HXUnixSemaphore( unInitialCount )
  344. {
  345.     //Init the sem to non-shared and count passed in.
  346.     if( sem_init( &m_semaphore, 0, m_unInitialCount ) < 0 )
  347.     {
  348. #ifdef _DEBUG
  349.         fprintf( stderr, "Can't init semaphore: %d %sn", errno, strerror(errno) );
  350. #endif
  351.     }
  352. }
  353. HXPthreadSemaphore::~HXPthreadSemaphore()
  354. {
  355.     sem_destroy( &m_semaphore );
  356. }
  357. HX_RESULT HXPthreadSemaphore::_Post()
  358. {
  359.     HX_RESULT retVal = HXR_OK;
  360.     //Init the sem to non-shared and count passed in.
  361.     if( sem_post(&m_semaphore) < 0 )
  362.     {
  363. #ifdef _DEBUG
  364.         fprintf( stderr, "Can't post to semaphore: %d %sn", errno, strerror(errno) );
  365. #endif
  366.         retVal = HXR_FAIL;
  367.     }
  368.     return retVal;
  369. }
  370. HX_RESULT HXPthreadSemaphore::_Wait()
  371. {
  372.     //sem_wait always returns zero.
  373.     sem_wait( &m_semaphore );
  374.     return HXR_OK;
  375. }
  376. HX_RESULT HXPthreadSemaphore::_TryWait()
  377. {
  378.     HX_RESULT retVal  = HXR_OK;
  379.     int       nResult = 0;
  380.     nResult = sem_trywait( &m_semaphore );
  381.     if( nResult<0 && errno == EAGAIN )
  382.     {
  383.         retVal = HXR_WOULD_BLOCK;
  384.     }
  385.     else if( nResult < 0 )
  386.     {
  387. #ifdef _DEBUG
  388.         fprintf( stderr, "Can't wait on semaphore: %d %sn", errno, strerror(errno) );
  389. #endif
  390.         retVal = HXR_FAIL;
  391.     }
  392.     return retVal;
  393. }
  394. // #ifdef _TIMEDWAITS_RECURSIVE_MUTEXES    
  395. // HX_RESULT HXPthreadSemaphore::_TimedWait(UINT32 unTimeOut )
  396. // {
  397. //     HX_RESULT ret = HXR_OK;
  398. //     struct timeval  now;
  399. //     struct timespec timeout;
  400. //     int retcode;
  401. //     gettimeofday(&now, NULL);
  402. //     long int waitSeconds = unTimeOut/1000;
  403. //     long int nanoSeconds = (unTimeOut-(waitSeconds*1000))*1000000;
  404. //     if( nanoSeconds >= 1000000000 )
  405. //     {
  406. //         nanoSeconds -= 1000000000;
  407. //         waitSeconds += 1;
  408. //     }
  409.     
  410. //     timeout.tv_sec  = now.tv_sec+waitSeconds;
  411. //     timeout.tv_nsec = now.tv_usec*1000+nanoSeconds;
  412. //     if( timeout.tv_nsec >= 1000000000 )
  413. //     {
  414. //         timeout.tv_nsec -= 1000000000;
  415. //         timeout.tv_sec  += 1;
  416. //     }
  417. //     //XXXgfw TEST TEST TEST
  418. //     retcode = sem_timedwait(&m_semaphore, &timeout);
  419.     
  420. //     if(retcode==-1)
  421. //     {
  422. //         ret = HXR_FAIL;
  423. //         //We really could use a HXR_TIMEDOUT.
  424. //         if( errno == ETIMEDOUT )
  425. //             ret = HXR_WOULD_BLOCK;
  426. //     }
  427. //     return ret;
  428. // }
  429. // #endif    
  430. HX_RESULT HXPthreadSemaphore::_GetValue( int* pnCount)
  431. {
  432.     //sem_getvalue always returns zero.
  433.     sem_getvalue( &m_semaphore, pnCount );
  434.     return HXR_OK;
  435. }
  436. #else
  437. // now  the _MAC_UNIX case...
  438. //=======================================================================
  439. //
  440. //                      HXPthreadMacSemaphore
  441. //                      ---------------------
  442. //
  443. //=======================================================================
  444. HXPthreadMacSemaphore::HXPthreadMacSemaphore(UINT32 unInitialCount)
  445.     : HXUnixSemaphore( unInitialCount )
  446. {
  447.     //Init the sem to non-shared and count passed in.
  448.     char buf[32];
  449.     sprintf(buf, "%s", tmpnam(NULL));
  450.     sem_t* sem = sem_open(buf, O_CREAT, 0, m_unInitialCount);
  451.     if ((int)sem == SEM_FAILED)
  452.     {
  453. #ifdef _DEBUG
  454.         fprintf( stderr, "Can't open semaphore: %d %sn", errno, strerror(errno) );
  455. #endif
  456.     }
  457.     else
  458.     {
  459.         m_semaphore = sem;
  460.     }
  461. }
  462. HXPthreadMacSemaphore::~HXPthreadMacSemaphore()
  463. {
  464.     if ( sem_close(m_semaphore) < 0 )
  465.     {
  466. #ifdef _DEBUG
  467.         fprintf( stderr, "Can't close semaphore: %d %sn", errno, strerror(errno) );
  468. #endif
  469.     }
  470. }
  471. HX_RESULT HXPthreadMacSemaphore::_Post()
  472. {
  473.     HX_RESULT retVal = HXR_OK;
  474.     //Init the sem to non-shared and count passed in.
  475.     if( sem_post(m_semaphore) < 0 )
  476.     {
  477. #ifdef _DEBUG
  478.         fprintf( stderr, "Can't post to semaphore: %d %sn", errno, strerror(errno) );
  479. #endif
  480.         retVal = HXR_FAIL;
  481.     }
  482.     return retVal;
  483. }
  484. HX_RESULT HXPthreadMacSemaphore::_Wait()
  485. {
  486.     //sem_wait always returns zero.
  487.     if ( sem_wait( m_semaphore ) < 0)
  488.     {
  489. #ifdef _DEBUG
  490.         fprintf( stderr, "sem_wait failed: %d %sn", errno, strerror(errno) );
  491. #endif
  492.     }
  493.     return HXR_OK;
  494. }
  495. HX_RESULT HXPthreadMacSemaphore::_TryWait()
  496. {
  497.     HX_RESULT retVal  = HXR_OK;
  498.     int       nResult = 0;
  499.     nResult = sem_trywait( m_semaphore );
  500.     if( nResult<0 && errno == EAGAIN )
  501.     {
  502.         retVal = HXR_WOULD_BLOCK;
  503.     }
  504.     else if( nResult < 0 )
  505.     {
  506. #ifdef _DEBUG
  507.         fprintf( stderr, "Can't wait on semaphore: %d %sn", errno, strerror(errno) );
  508. #endif
  509.         retVal = HXR_FAIL;
  510.     }
  511.     return retVal;
  512. }
  513. HX_RESULT HXPthreadMacSemaphore::_GetValue( int* pnCount)
  514. {
  515.     //sem_getvalue always returns zero.
  516.     if ( sem_getvalue( m_semaphore, pnCount ) < 0 )
  517.     {
  518. #ifdef _DEBUG
  519.         fprintf( stderr, "sem_getvalue failed: %d %sn", errno, strerror(errno) );
  520. #endif
  521.     }
  522.     return HXR_OK;
  523. }
  524. #endif // _MAC_UNIX
  525. #endif //_UNIX_THREADS_SUPPORTED