00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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 };
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 };
00071
00072
00073 class TConsumerThread : public TThread
00074 {
00075
00076 protected:
00077
00078 void body (void);
00079 const int get (void) const;
00080
00081 };
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 };
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 }
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 }
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 }
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 }
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 }
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
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
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 }