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

Symbian

开发平台:

Visual C++

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