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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: tthreads.cpp,v 1.2.48.3 2004/07/09 01:44:00 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 <unistd.h> //for sleep
  51. #include "hxassert.h"
  52. #include "hxthread.h"
  53. #include "hxthread.h"
  54. #include "microsleep.h"
  55. #include "hlxclib/stdlib.h"
  56. #include "hxmsgs.h"  
  57. extern "C"
  58. {
  59.     
  60. //XXXgfw TODO
  61. //
  62. //  1) Add support for those advanced thread features some platforms
  63. //     support (timed waits, message passing, named objects, etc).
  64. //  2) Clean up all the memory leaks. If an error occurs I just return
  65. //     without cleaning up at all.    
  66. #define MAGIC_NUMBER 1234
  67. //Global int for tests...
  68. int nFlag = 0;
  69. HXMutex* pMutex = NULL;
  70. void* _threadFunc1(void* pData)
  71. {
  72.     fprintf( stderr, "Thread is running...n");
  73.     fprintf( stderr, "pData is %p and should match the magic number %pn",
  74.              pData, (void*)MAGIC_NUMBER);
  75.     if( pData != (void*)MAGIC_NUMBER )
  76.     {
  77.         fprintf( stderr, "FAILED:Thread arg is wrong...n" );
  78.         exit(1);
  79.     }
  80.     
  81.     sleep(3);
  82.     return pData;
  83. }
  84. void* _threadFunc2(void* pData)
  85. {
  86.     HXMutex* pMutex = (HXMutex*)pData;
  87.     fprintf( stderr, "Mutex test thread:  is running....n" );
  88.     fprintf( stderr, "Mutex test thread:  Going to lock mutex...n" );
  89.     nFlag = MAGIC_NUMBER;
  90.     pMutex->Lock();
  91.     nFlag = 0;
  92.     fprintf( stderr, "Mutex test thread:  Got mutex...exiting...n" );
  93.     pMutex->Unlock();
  94.     
  95.     return (void*)66;
  96. }
  97. void* _threadFuncEvent1(void* pData)
  98. {
  99.     HXEvent* pEvent = (HXEvent*)pData;
  100.     fprintf( stderr, "Event thread1:  is running....n" );
  101.     pEvent->Wait();
  102.     pMutex->Lock();
  103.     nFlag++;
  104.     pMutex->Unlock();
  105.     return (void*)0;
  106. }
  107. void* _threadFuncEvent2(void* pData)
  108. {
  109.     HXEvent* pEvent = (HXEvent*)pData;
  110.     fprintf( stderr, "Event thread2:  is running....n" );
  111.     pEvent->Wait();
  112.     pMutex->Lock();
  113.     nFlag++;
  114.     pMutex->Unlock();
  115.     return (void*)0;
  116. }
  117. void _timerProc1( void*   hwnd,
  118.                  UINT32  msg,
  119.                  UINT32  id,
  120.                  ULONG32 CurrentTime)
  121. {
  122.     fprintf( stderr, "id: %d  current time: %lun", id, CurrentTime );
  123.     nFlag++;
  124. }
  125. typedef struct _stuff
  126. {
  127.     HXThread* pThread;
  128.     HXEvent*  pEvent;
  129. } ST_STUFF;
  130. void* _timerProc2(void* pData)
  131. {
  132.     ST_STUFF* pTmp = (ST_STUFF*)pData;
  133.     HXEvent*  pEvent = (HXEvent*)pTmp->pEvent;
  134.     HXThread* pThread = (HXThread*)pTmp->pThread;
  135.     HXThreadMessage msgTmp;
  136.     
  137.     fprintf( stderr, "_timerProc2: is running....n" );
  138.     while(1)
  139.     {
  140.         if( HXR_OK == pThread->GetMessage(&msgTmp))
  141.         {
  142.             //Got a message. If it is HXMSG_QUIT get our of here.
  143.             if( msgTmp.m_ulMessage == HXMSG_QUIT )
  144.             {
  145.                 fprintf( stderr, "Thread got quit message.n" ); 
  146.                 break;
  147.             }
  148.             if( msgTmp.m_ulMessage == HXMSG_ASYNC_TIMER )
  149.             {
  150.                 fprintf( stderr, "nFlag: %dn", nFlag ); 
  151.                 nFlag++;
  152.             }
  153.             if( nFlag >= 5 )
  154.             {
  155.                 fprintf( stderr, "Telling main thread to wake up...n" ); 
  156.                 //Tell the master thread to wake up and kill us.
  157.                 pEvent->SignalEvent();
  158.             }
  159.             
  160.         }
  161.     }
  162.     nFlag = 0;
  163.     return (void*)0;
  164. }
  165. int main()
  166. {
  167.     fprintf( stderr, "Threads test running....n" );
  168.     ////////////////////////
  169.     //
  170.     // THREAD TESTS
  171.     //
  172.     ////////////////////////
  173.     //Test thread creation.
  174.     HX_RESULT res = HXR_OK;
  175.     HXThread* pThread = NULL;
  176.     
  177.     res = HXThread::MakeThread(pThread);
  178.     if( !pThread || FAILED(res) )
  179.     {
  180.         fprintf( stderr, "FAILED:Failed to make thread.n" );
  181.         return 1;
  182.     }
  183.     //Run the thread and make sure the two thread IDs are different.
  184.     //ThreadFunc1 will sleep for 5 seconds. We can also test the basic
  185.     //join at this point.
  186.     pThread->CreateThread(_threadFunc1, (void*)MAGIC_NUMBER );
  187.     //Thread is running, get the IDs..
  188.     ULONG32 otherThread = 0;
  189.     ULONG32 myThread = pThread->GetCurrentThreadID();
  190.     pThread->GetThreadId(otherThread);
  191.     if( 0==otherThread || otherThread==myThread || 0==myThread )
  192.     {
  193.         fprintf( stderr, "FAILED:Thread IDs should not match and should not be zero.n" );
  194.         return 1;
  195.     }
  196.     fprintf( stderr, "Thread ID 1: %lu   Thread ID 2: %lun", myThread, otherThread ); 
  197.     //This should let us join on the other thread. In the current implementation
  198.     //there is not way to return the exit value of the thread.
  199.     fprintf( stderr, "Joining thread. Should be a 4-5 second wait...n" ); 
  200.     pThread->Exit(0);
  201.     fprintf( stderr, "Back! Yeah...n" );
  202.     sleep(1);
  203.     
  204.     //Clean up the thread.
  205.     HX_DELETE( pThread );
  206.     
  207.     ////////////////////////
  208.     //
  209.     // MUTEX TESTS
  210.     //
  211.     ////////////////////////
  212.     HXMutex::MakeMutex(pMutex);
  213.     //Lock it...
  214.     fprintf( stderr, "Going to lock the mutex for the first time. If this deadn" );
  215.     fprintf( stderr, "locks...you did not pass the test..n" );
  216.     res = pMutex->Lock();
  217.     if( FAILED(res) )
  218.     {
  219.         fprintf( stderr, "FAILED:Lock failed...n" );
  220.         return 1;
  221.     }
  222.     //Test to make sure its recursive as our mutexes must be...
  223.     fprintf( stderr, "Going to lock the mutex for the second time. If this deadn" );
  224.     fprintf( stderr, "locks...you did not pass the test..n" );
  225.     res = pMutex->Lock();
  226.     if( FAILED(res) )
  227.     {
  228.         fprintf( stderr, "FAILED: recursive Lock failed...n" );
  229.         return 1;
  230.     }
  231.     //Now we have the mutex locked 2 times, spawn a thread and make
  232.     //sure it can't lock it.
  233.     HXThread::MakeThread(pThread);
  234.     if( !pThread || FAILED(res) )
  235.     {
  236.         fprintf( stderr, "FAILED:Failed to make thread for mutex test.n" );
  237.         return 1;
  238.     }
  239.     //Thread func 2 will just try and lock the mutex we pass in.
  240.     //It better block until we release it 2 times...
  241.     nFlag = 0;
  242.     pThread->CreateThread(_threadFunc2, (void*)pMutex );
  243.     
  244.     //make sure the thread has a chance to run and set the magic number.
  245.     sleep(1);
  246.     fprintf( stderr, "test thread should now be blocked...n" );
  247.     if( nFlag != MAGIC_NUMBER )
  248.     {
  249.         fprintf( stderr, "FAILED:test thread did no block on locked mutex...n" );
  250.         return 1;
  251.     }
  252.     
  253.     fprintf( stderr, "Unlocking the mutex once...test thread should not be free.n" );
  254.     pMutex->Unlock();
  255.     sleep(1);
  256.     if( nFlag != MAGIC_NUMBER )
  257.     {
  258.         fprintf( stderr, "FAILED:mutex lock count does not work...n" );
  259.         return 1;
  260.     }
  261.     
  262.     fprintf( stderr, "Unlocking the mutex again. This should free test thread..n" );
  263.     pMutex->Unlock();
  264.     sleep(1);
  265.     if( nFlag != 0 )
  266.     {
  267.         fprintf( stderr, "FAILED: test thread should have been unlocked....n" );
  268.         return 1;
  269.     }
  270.     
  271.     HX_DELETE( pThread );
  272.     HX_DELETE( pMutex );
  273.     
  274.         
  275.     ////////////////////////
  276.     //
  277.     // EVENT TESTS
  278.     //
  279.     ////////////////////////
  280.      HXEvent* pEvent = NULL;
  281.     HXEvent::MakeEvent(pEvent, "foo", FALSE);
  282.     if( !pEvent )
  283.     {
  284.         fprintf( stderr, "FAILED: Can't make events...n" );
  285.         return 1;
  286.     }
  287.     
  288.     //Non manual resets events. Only one thread should wake up each signal.
  289.      HXThread* pThread1 = NULL;
  290.     HXThread* pThread2 = NULL;
  291.     
  292.     HXThread::MakeThread(pThread1);
  293.     HXThread::MakeThread(pThread2);
  294.     HXMutex::MakeMutex(pMutex); //to protect out flag.
  295.     if( !pThread1 || !pThread2 || !pMutex )
  296.     {
  297.         fprintf( stderr, "FAILED:Failed to make thread for Event test.n" );
  298.         return 1;
  299.     }
  300.     nFlag = 0;
  301.     
  302.     //Thread func 2 will just try and lock the mutex we pass in.
  303.     //It better block until we release it 2 times...
  304.     res = pThread1->CreateThread(_threadFuncEvent1, (void*)pEvent );
  305.     if( FAILED(res) )
  306.     {
  307.         fprintf( stderr, "FAILED: Can't create Event Thread1n" );
  308.         return 1;
  309.     }
  310.     
  311.     res = pThread2->CreateThread(_threadFuncEvent2, (void*)pEvent );
  312.     if( FAILED(res) )
  313.     {
  314.         fprintf( stderr, "FAILED: Can't create Event Thread2n" );
  315.         return 1;
  316.     }
  317.     sleep(1);
  318.     //Both threads should be waiting on us to signal the event then.
  319.     if( nFlag != 0 )
  320.     {
  321.         fprintf( stderr, "FAILED: nFlag should be zero.n" );
  322.         return 1;
  323.     }
  324.     //Let one thread go...
  325.     pEvent->SignalEvent();
  326.     sleep(1);
  327.     if( nFlag != 1 )
  328.     {
  329.         //Either the thread didn't go or both went. Either way its
  330.         //bad.
  331.         fprintf( stderr, "FAILED: nFlag should be 1.n" );
  332.         return 1;
  333.     }
  334.     //Let the next thread go...
  335.     pEvent->SignalEvent();
  336.     sleep(1);
  337.     if( nFlag != 2 )
  338.     {
  339.         //Either the thread didn't go or both went. Either way its
  340.         //bad.
  341.         fprintf( stderr, "FAILED: nFlag should be 2.n" );
  342.         return 1;
  343.     }
  344.     HX_DELETE(pEvent);
  345.     HX_DELETE(pThread1);
  346.     HX_DELETE(pThread2);
  347.     //Now test manual reset ones...
  348.     HXEvent::MakeEvent(pEvent, "foo", TRUE);
  349.     if( !pEvent )
  350.     {
  351.         fprintf( stderr, "FAILED: Can't make events...n" );
  352.         return 1;
  353.     }
  354.     
  355.     //Non manual resets events. Only one thread should wake up each signal.
  356.     HXThread::MakeThread(pThread1);
  357.     HXThread::MakeThread(pThread2);
  358.     if( !pThread1 || !pThread2 || !pMutex )
  359.     {
  360.         fprintf( stderr, "FAILED:Failed to make thread for Event test.n" ); 
  361.         return 1;
  362.     }
  363.     nFlag = 0;
  364.     
  365.     //Thread func 2 will just try and lock the mutex we pass in.
  366.     //It better block until we release it 2 times...
  367.     pThread1->CreateThread(_threadFuncEvent1, (void*)pEvent );
  368.     pThread2->CreateThread(_threadFuncEvent2, (void*)pEvent );
  369.     sleep(1);
  370.     //Both thread should be waiting on the broadcast...
  371.     if( nFlag != 0 )
  372.     {
  373.         fprintf( stderr, "FAILED: nFlag should be zero.n" );
  374.         return 1;
  375.     }
  376.     //Let all threads go...
  377.     pEvent->SignalEvent();
  378.     sleep(1);
  379.     
  380.     if( nFlag != 2 )
  381.     {
  382.         fprintf( stderr, "FAILED: both threads should have gone..n" );
  383.         return 1;
  384.     }
  385.     
  386.     HX_DELETE(pEvent);
  387.     HX_DELETE(pThread1);
  388.     HX_DELETE(pThread2);
  389.     HX_DELETE(pMutex);
  390.     ////////////////////////
  391.     //
  392.     // ASYNC TIMER TESTS
  393.     //
  394.     ////////////////////////
  395.     //Try a timer that calls a proc first....
  396.     fprintf( stderr, "You should see our timer proc fire every second...n" );
  397.     nFlag = 0;
  398.     int id = HXAsyncTimer::SetTimer( 1000, _timerProc1 );
  399.     sleep(5);
  400.     HXAsyncTimer::KillTimer(id);
  401.     int ttt = nFlag;
  402.     fprintf( stderr, "You should see no more timer procs....n" ); 
  403.     sleep(3);
  404.     //The timer proc incrments nFlag each time it is called. So, since
  405.     //we slept for 5 seconds and we were suppose to call it every second
  406.     //I will take it as a fail if it hasn't at least been incremnted
  407.     //at least once. Also, if nFlag gets incremented again it didn't kill
  408.     //correctly.
  409.     if( 0==ttt )
  410.     {
  411.         fprintf( stderr, "FAILED: The timer proc didn't ever fire.n" );
  412.         return 1;
  413.     }
  414.     if( nFlag!=ttt )
  415.     {
  416.         fprintf( stderr, "FAILED: The timer proc didn't stop firing when we killed it.n" );
  417.         return 1;
  418.     }
  419.     
  420.     
  421.     //Now try posting timer messages to a thread....
  422.     HXThread::MakeThread(pThread1);
  423.     if( !pThread1  )
  424.     {
  425.         fprintf( stderr, "FAILED:Failed to make thread for Timer test.n" ); 
  426.         return 1;
  427.     }
  428.     nFlag = 0;
  429.     
  430.     //Send it a few messages. When it gets 5 messages it will signal
  431.     //this event that we are waiting on and then we will kill the timer
  432.     //and send it a quit event to it can die.
  433.     HXEvent::MakeEvent(pEvent, "foo", TRUE);
  434.     if( !pEvent )
  435.     {
  436.         fprintf( stderr, "FAILED: Can't make event for timer test.n" );
  437.         return 1;
  438.     }
  439.     ST_STUFF stuff;
  440.     stuff.pEvent = pEvent;
  441.     stuff.pThread = pThread1;
  442.     
  443.         
  444.     pThread1->CreateThread(_timerProc2, (void*)&stuff );
  445.     id = HXAsyncTimer::SetTimer( 1000, pThread1 );
  446.     pEvent->Wait();
  447.     //Verify that the thread got at least 5 async messages.
  448.     if( nFlag < 5 )
  449.     {
  450.         fprintf( stderr, "FAILED: _timerProc2 didn't get enough messages.n" );
  451.         return 1;
  452.     }
  453.     
  454.     //Kill the timer before we destroy the thread.
  455.     HXAsyncTimer::KillTimer(id);
  456.     
  457.     //When the thread exits it will set the nFlag back to zero...
  458.     HXThreadMessage msgQuit(HXMSG_QUIT, NULL, NULL);
  459.     pThread1->PostMessage( &msgQuit );
  460.     //Join the thread.
  461.     pThread1->Exit(0);
  462.     if( nFlag != 0 )
  463.     {
  464.         fprintf( stderr, "FAILED: Thread didn't quit correctlyn" );
  465.         return 1;
  466.     }
  467.     HX_DELETE( pThread1 );
  468.     fprintf( stderr, "PASSED!n" ); 
  469.     return 0;
  470. }
  471. }