Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members  

test-thread.cc

00001 /*
00002 *  Name:      test-thread.cc
00003 *  Author:    Rafael Jesus Alcantara Perez
00004 *  Summary:   Test for threads
00005 *  Date:      $Date: 2003/04/14 00:18:36 $
00006 *  Revision:  $Revision: 1.1 $
00007 *
00008 *  Copyright (C) 1994-2002  Rafael Jesus Alcantara Perez <rafa@dedalo-ing.com>
00009 *
00010 *  This program is free software; you can redistribute it and/or modify
00011 *  it under the terms of the GNU General Public License as published by
00012 *  the Free Software Foundation; either version 2 of the License, or
00013 *  (at your option) any later version.
00014 *
00015 *  This program is distributed in the hope that it will be useful,
00016 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 *  GNU General Public License for more details.
00019 *
00020 *  You should have received a copy of the GNU General Public License
00021 *  along with this program; if not, write to the Free Software
00022 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00023 *  MA 02111-1307, USA.
00024 */
00025 
00026 #include <iostream>
00027 #include <mpcl/system/all.hh>
00028 #include <mpcl/test.h>
00029 #include <queue>
00030 
00031 
00032 using mpcl::system::TCondition;
00033 using mpcl::system::TMutex;
00034 using mpcl::system::TThread;
00035 using mpcl::system::tSystem;
00036 using std::queue;
00037 
00038 
00039 //
00040 //  L O C A L   V A R I A B L E S
00041 //
00042 
00043 static int            _iSharedCounter;
00044 static TMutex         _tMutex;
00045 static queue<int>     _tQueue;
00046 static TCondition     _tNotEmptyCondition (_tMutex);
00047 static TCondition     _tNotFullCondition  (_tMutex);
00048 static bool           _gError         = false;
00049 static const size_t   _kzMaxQueueSize = 16;
00050 
00051 
00052 class TExampleThread : public TThread
00053 {
00054 
00055   protected:
00056   
00057     void body (void);
00058 
00059 };  // class TExampleThread
00060 
00061 
00062 class TProducerThread : public TThread
00063 {
00064 
00065   protected:
00066   
00067     void body (void);
00068     void put (const int kiSOURCE_DATA) const;
00069 
00070 };  // class TProducerThread
00071 
00072 
00073 class TConsumerThread : public TThread
00074 {
00075 
00076   protected:
00077   
00078     void body (void);
00079     const int get (void) const;
00080 
00081 };  // class TExampleThread
00082 
00083 
00084 class TThrowingThread : public TThread
00085 {
00086 
00087   public:
00088 
00089     int   iExitCode;
00090 
00091 
00092   protected:
00093   
00094     void body (void)
00095     {
00096       try
00097       {
00098         iExitCode = 1;
00099         throw 0;
00100       }
00101       catch (int)
00102       {
00103         iExitCode = 0;
00104       }
00105     }
00106 
00107 };  // class TExampleThread
00108 
00109 
00110 void TExampleThread::body (void)
00111 {
00112 
00113   for (register size_t J = 0; ( J < 50000 ) ;++J)
00114   {
00115     _tMutex.lock();
00116     ++_iSharedCounter;
00117     _tMutex.unlock();
00118   }
00119 
00120 }  // TExampleThread::body()
00121 
00122 
00123 void TProducerThread::body (void)
00124 {
00125 
00126   for (register int J = 0; ( J < 50000 ) ;++J)
00127   {
00128     put (J);
00129   }
00130 
00131 }  // TProducerThread::body()
00132 
00133 
00134 void TProducerThread::put (const int kiSOURCE_DATA) const
00135 {
00136   
00137   _tMutex.lock();
00138   if ( _tQueue.size() == _kzMaxQueueSize )
00139   {
00140     _tNotFullCondition.wait();
00141   }
00142   _tQueue.push (kiSOURCE_DATA);
00143   _tNotEmptyCondition.signal();
00144   _tMutex.unlock();
00145 
00146 }  // TProducerThread::put()
00147 
00148 
00149 void TConsumerThread::body (void)
00150 {
00151 
00152   TEST_INIT ("tests for consumer");
00153   for (register int J = 0; ( J < 50000 ) ;++J)
00154   {
00155     if ( J != get() )
00156     {
00157       _tMutex.lock();
00158       _gError = true;
00159       _tMutex.unlock();
00160     }
00161   }
00162   TEST_END;
00163 
00164 }  // TConsumerThread::body()
00165 
00166 
00167 const int TConsumerThread::get (void) const
00168 {
00169 
00170   int   iData;
00171   
00172   _tMutex.lock();
00173   if ( _tQueue.empty() )
00174   {
00175     _tNotEmptyCondition.wait();
00176   }
00177   iData = _tQueue.front();
00178   _tQueue.pop();
00179   _tNotFullCondition.signal();
00180   _tMutex.unlock();
00181   return iData;
00182 
00183 }  // TConsumerThread::get()
00184 
00185 
00187 int main (void)
00188 {
00189 
00190   TExampleThread    tExample1;
00191   TExampleThread    tExample2;
00192   TProducerThread   tProducerThread;
00193   TConsumerThread   tConsumerThread;
00194 
00195   TEST_INIT ("tests for class 'TThread'");
00196 
00197   tExample1.start();
00198   tExample2.start();
00199   tSystem.sleep (5);
00200   tSystem.yield();
00201   tExample1.join();
00202   tExample2.join();
00203   TEST_NUMBERS (100000, _iSharedCounter);
00204 
00205   tProducerThread.start();
00206   tConsumerThread.start();
00207   tProducerThread.join();
00208   tConsumerThread.join();
00209   TEST_NUMBERS (false, _gError);
00210 
00211   //
00212   //  Tests that threads are catched in the right place.
00213   //
00214   {
00215     TProducerThread   tProducerThreadA;
00216     TConsumerThread   tConsumerThreadA;
00217 
00218     try
00219     {
00220       
00221       tProducerThreadA.start();
00222       tConsumerThreadA.start();
00223       throw 1;
00224       TEST_FAIL;
00225     }
00226     catch (int)
00227     {
00228       tProducerThreadA.join();
00229       tConsumerThreadA.join();
00230       TEST_PASS;
00231     }
00232   }
00233 
00234   //
00235   //  Tests that exceptions thrown in threads are catched in the right place.
00236   //
00237   try
00238   {
00239     TThrowingThread   tThrowingThread;
00240 
00241     tThrowingThread.start();
00242     tThrowingThread.join();
00243     TEST_NUMBERS (0, tThrowingThread.iExitCode);
00244     TEST_PASS
00245   }
00246   catch (int)
00247   {
00248     TEST_FAIL
00249   }
00250   TEST_MEMORY_STATUS;
00251   TEST_RETURN_CODE;
00252 
00253 }  // main()

Generated on Mon Oct 13 02:35:24 2003 for MPCL by doxygen1.2.18