tthreads.cpp
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 14k
Category:

Symbian

Development Platform:

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