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

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 <synch.h>
  41. #include <thread.h>
  42. #include "solaristhreads.h"
  43. //=======================================================================
  44. //
  45. //                      HXSolarisThread
  46. //                   ----------------------
  47. //
  48. //=======================================================================
  49. HXSolarisThread::HXSolarisThread()
  50.     : HXUnixThread()
  51. {}
  52. HXSolarisThread::~HXSolarisThread()
  53. {}
  54. HX_RESULT HXSolarisThread::_thread_create( ULONG32& ulThreadID, void*(pfExecFunc(void*)), void* pArg )
  55. {
  56.     HX_RESULT retVal = HXR_OK;
  57.     thread_t threadID=0;
  58.     int nCode = thr_create(NULL, 0, pfExecFunc, pArg, 0, &threadID);
  59.     ulThreadID = threadID;
  60.     if (nCode!=0)
  61.     {
  62.         ulThreadID = 0;
  63.         retVal = HXR_FAIL;
  64.     }
  65.     return retVal;
  66. }
  67. ULONG32 HXSolarisThread::_thread_self()
  68. {
  69.     return thr_self();
  70. }
  71. void HXSolarisThread::_thread_exit(UINT32 unExitCode)
  72. {
  73.     thr_exit( (void*)unExitCode );
  74. }
  75. void HXSolarisThread::_thread_cancel(ULONG32 ulThreadID)
  76. {
  77.     HX_ASSERT( "_thread_cancel not supported on Solaris threads" == NULL );
  78. }
  79. ULONG32 HXSolarisThread::_thread_join(ULONG32 ulThreadID)
  80. {
  81.     void* pvRetVal = NULL;
  82.     thr_join( ulThreadID, NULL, &pvRetVal );
  83.     return (ULONG32)(PTR_INT)pvRetVal;
  84. }
  85. //=======================================================================
  86. //
  87. //                      HXSolarisMutex
  88. //                   ------------------
  89. //
  90. //=======================================================================
  91. HXSolarisMutex::HXSolarisMutex()
  92.     : HXUnixMutex(),
  93.       m_ulOwnerThread(0),
  94.       m_ulLockCount(0)
  95. {
  96.     mutex_init( &m_mutex, USYNC_THREAD, NULL ); 
  97.     mutex_init( &m_mtxLockLock, USYNC_THREAD, NULL );
  98. }
  99.     
  100. HXSolarisMutex::~HXSolarisMutex()
  101. {
  102.     mutex_destroy( &m_mutex );
  103.     m_ulLockCount   = 0;
  104.     m_ulOwnerThread = 0;
  105. }
  106.     
  107. HX_RESULT HXSolarisMutex::_Lock()
  108. {
  109.     //We simulate recursive mutexes.
  110.     //No one owns this mutex.
  111.     if( m_ulOwnerThread != thr_self() )
  112.     {
  113.         //We are going to block for sure.
  114.         mutex_lock(&m_mutex);
  115.         //Take ownership.
  116.         mutex_lock(&m_mtxLockLock);
  117.         m_ulOwnerThread = thr_self();
  118.         m_ulLockCount   = 1;
  119.         mutex_unlock(&m_mtxLockLock);        
  120.     }
  121.     else
  122.     {
  123.         //We alread have it locked. Just increment the lock count
  124.         mutex_lock(&m_mtxLockLock);
  125.         m_ulLockCount++;
  126.         mutex_unlock(&m_mtxLockLock);        
  127.     }
  128.     return HXR_OK;
  129. }
  130.     
  131. HX_RESULT HXSolarisMutex::_Unlock()
  132. {
  133.     //Sanity checks.
  134.     HX_ASSERT( m_ulLockCount != 0 && m_ulOwnerThread == thr_self() );
  135.     if( m_ulLockCount == 0 || m_ulOwnerThread!=thr_self() )
  136.         return HXR_FAIL;
  137.     mutex_lock(&m_mtxLockLock);
  138.     m_ulLockCount--;
  139.     if( m_ulLockCount == 0 )
  140.     {
  141.         //We are really done with it. Do the real unlock now.
  142.         m_ulOwnerThread = 0;
  143.         mutex_unlock(&m_mutex);
  144.     }
  145.     mutex_unlock(&m_mtxLockLock);  
  146.     return HXR_OK;
  147. }
  148.     
  149. HX_RESULT HXSolarisMutex::_TryLock()
  150. {
  151. //    HX_ASSERT( "Trylock isn't compatible with our home-grown recursive mutexes yet!" ==NULL );
  152.     //Warning: this is just a blind wrapper around trylock. It doesn't take into accout
  153.     //our simulation or recursive mutexes.
  154.     return (mutex_trylock(&m_mutex)==0) ? HXR_OK : HXR_FAIL;
  155. }
  156. //=======================================================================
  157. //
  158. //                      HXSolarisSemaphore
  159. //                   ------------------
  160. //
  161. //=======================================================================
  162. HXSolarisSemaphore::HXSolarisSemaphore(UINT32 unInitialCount)
  163.     : HXUnixSemaphore( unInitialCount )
  164. {
  165.     //Init the sem to non-shared and count passed in.
  166.     if( sema_init( &m_semaphore, m_unInitialCount, USYNC_THREAD, NULL ) < 0 )
  167.     {
  168. #ifdef _DEBUG
  169.         fprintf( stderr, "Can't init semaphore: %d %sn", errno, strerror(errno) );
  170. #endif
  171.     }
  172. }
  173. HXSolarisSemaphore::~HXSolarisSemaphore()
  174. {
  175.     sema_destroy( &m_semaphore );
  176. }
  177. HX_RESULT HXSolarisSemaphore::_Post()
  178. {
  179.     HX_RESULT retVal = HXR_OK;
  180.     //Init the sem to non-shared and count passed in.
  181.     if( sema_post(&m_semaphore) < 0 )
  182.     {
  183. #ifdef _DEBUG
  184.         fprintf( stderr, "Can't post to semaphore: %d %sn", errno, strerror(errno) );
  185. #endif
  186.         retVal = HXR_FAIL;
  187.     }
  188.     return retVal;
  189. }
  190. HX_RESULT HXSolarisSemaphore::_Wait()
  191. {
  192.     //sem_wait always returns zero.
  193.     sema_wait( &m_semaphore );
  194.     return HXR_OK;
  195. }
  196. HX_RESULT HXSolarisSemaphore::_TryWait()
  197. {
  198.     HX_RESULT retVal  = HXR_OK;
  199.     int       nResult = 0;
  200.     
  201.     nResult = sema_trywait( &m_semaphore );
  202.     if( nResult != 0 )
  203.     {
  204.         retVal = HXR_WOULD_BLOCK;
  205.     }
  206.     return retVal;
  207. }
  208. HX_RESULT HXSolarisSemaphore::_GetValue( int* pnCount)
  209. {
  210.     //sem_getvalue always returns zero.
  211.     HX_ASSERT( "_GetValue is not supported by Solaris threads"==NULL );
  212.     
  213.     return HXR_OK;
  214. }
  215. HXSolarisCondition::HXSolarisCondition(HXUnixMutex*& pMutex)
  216. {
  217.     HX_ASSERT( pMutex == NULL );
  218.     //Create the mutex we need to associate with this cond.
  219.     
  220.     m_pMutex = new HXSolarisMutex();
  221.     pMutex = (HXUnixMutex*)m_pMutex;
  222.     //Init our cond var.
  223.     cond_init( &m_cond, NULL, NULL );
  224. }
  225. HXSolarisCondition::~HXSolarisCondition()
  226. {
  227.     cond_destroy(&m_cond);
  228.     HX_DELETE( m_pMutex );
  229. }
  230. HX_RESULT HXSolarisCondition::_Signal()
  231. {
  232.     cond_signal(&m_cond);
  233.     return HXR_OK;
  234. }
  235. HX_RESULT HXSolarisCondition::_Broadcast()
  236. {
  237.     cond_broadcast(&m_cond);
  238.     return HXR_OK;
  239. }
  240. HX_RESULT HXSolarisCondition::_Wait()
  241. {
  242.     HX_ASSERT( m_pMutex );
  243.     //m_pMuex MUST BE LOCKED ALL READY!
  244.     cond_wait(&m_cond, m_pMutex->_GetSolarisMutex());
  245.     return HXR_OK;
  246. }
  247. HX_RESULT HXSolarisCondition::_TimedWait(UINT32 unTimeOut)
  248. {
  249.     //m_pMuex MUST BE LOCKED ALL READY!
  250.     HX_RESULT      ret = HXR_OK;
  251.     struct timeval now;
  252.     timestruc_t    timeout;
  253.     int            retcode;
  254.     gettimeofday(&now, NULL);
  255.     long int waitSeconds = unTimeOut/1000;
  256.     long int nanoSeconds = (unTimeOut-(waitSeconds*1000))*1000000;
  257.     timeout.tv_sec  = now.tv_sec+waitSeconds;
  258.     timeout.tv_nsec = now.tv_usec*1000+nanoSeconds;
  259.     if( timeout.tv_nsec >= 1000000000 )
  260.     {
  261.         timeout.tv_nsec -= 1000000000;
  262.         timeout.tv_sec  += 1;
  263.     }
  264.     retcode = cond_timedwait(&m_cond, m_pMutex->_GetSolarisMutex(), &timeout);
  265.     
  266.     if(retcode==-1)
  267.     {
  268.         ret = HXR_FAIL;
  269.         //We really could use a HXR_TIMEDOUT.
  270.         if( errno == ETIMEDOUT )
  271.             ret = HXR_WOULD_BLOCK;
  272.     }
  273.     return ret;
  274. }
  275. #endif //_UNIX_THREADS_SUPPORTED