00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef BDEQUETEST_H_
00017 #define BDEQUETEST_H_
00018
00019 #include <cppunit/extensions/HelperMacros.h>
00020 #include <cppunit/TestAssert.h>
00021 #include "baseTest.h"
00022
00023 #include <algorithm>
00024
00025 namespace test {
00026 using namespace amino;
00027
00028 template<typename DequeType, typename ParaType, char const* CLASS_NAME>
00029 class BDequeTest: public CppUnit::TestFixture, public BaseTest<ParaType> {
00030 CPPUNIT_TEST_SUITE(BDequeTest);
00031 CPPUNIT_TEST(testPushRightMT);
00032 CPPUNIT_TEST(test4DirectionMT);
00033 CPPUNIT_TEST(testProducerConsumer);
00034 CPPUNIT_TEST_SUITE_END();
00035
00036 private:
00037 DequeType *deque;
00038 public:
00039 BDequeTest() {
00040 }
00041
00042 DequeType * getDeque() {
00043 return deque;
00044 }
00045
00046 void setUp() {
00047 deque = new DequeType();
00048 }
00049
00050 void reset() {
00051 delete deque;
00052 deque = new DequeType();
00053 }
00054
00055 void tearDown() {
00056 delete deque;
00057 }
00058
00062 void testPushRightMT();
00063 void test4DirectionMT();
00064
00065 void testProducerConsumer();
00066 };
00067
00068 template<typename DequeType, typename ParaType, char const* CLASS_NAME>
00069 class Thread4Dir: public TestThread<ParaType> {
00070 private:
00071 DequeType *deque;
00072 BDequeTest<DequeType, ParaType, CLASS_NAME> *testcase;
00073 int operationNum;
00074
00075 public:
00076 Thread4Dir(DequeType * q, BDequeTest<DequeType, ParaType, CLASS_NAME> * qt, int nOperation) :
00077 deque(q), testcase(qt), operationNum(nOperation) {
00078 }
00079
00080 static atomic<ParaType> checksum;
00081
00082 static ParaType getChecksum() {
00083 return checksum.load(memory_order_relaxed);
00084 }
00085
00086 void* run() {
00087 #ifdef DEBUG
00088 int repeat =0;
00089 ParaType prev;
00090 #endif
00091 for (int i = 0; i < operationNum; ++i) {
00092 if (i % 2 == 0) {
00093 deque->pushRight(i);
00094 this->inVec.push_back(i);
00095 ParaType tmp;
00096 if(deque->takeLeft(tmp)) {
00097 this->outVec.push_back(tmp);
00098 }
00099 } else {
00100 deque->pushLeft(i);
00101 this->inVec.push_back(i);
00102 ParaType tmp;
00103 if(deque->takeRight(tmp)) {
00104 this->outVec.push_back(tmp);
00105 }
00106 #ifdef DEBUG
00107
00108 if (tmp == prev)
00109 repeat++;
00110 else {
00111 prev = tmp;
00112 repeat=0;
00113 }
00114
00115 if (repeat>10)
00116 cout<< "I got too many equal element" << endl;
00117 #endif
00118 }
00119 }
00120 return NULL;
00121 }
00122 };
00123
00124 template<typename DequeType, typename ParaType, const char * CLASS_NAME>
00125 atomic<ParaType> Thread4Dir<DequeType, ParaType, CLASS_NAME>::checksum;
00126
00127 template<typename DequeType, typename ParaType, char const* CLASS_NAME>
00128 class ThreadPushRight: public TestThread<ParaType> {
00129 private:
00130 DequeType *deque;
00131 BDequeTest<DequeType, ParaType, CLASS_NAME> *testcase;
00132 int operationNum;
00133
00134 public:
00135 ThreadPushRight(DequeType * q,
00136 BDequeTest<DequeType, ParaType, CLASS_NAME> * qt, int nOperation) :
00137 deque(q), testcase(qt), operationNum(nOperation) {
00138 }
00139
00140 static atomic<ParaType> checksum;
00141
00142 static ParaType getChecksum() {
00143 return checksum.load(memory_order_relaxed);
00144 }
00145
00146 void* run() {
00147 for (int i = 0; i < operationNum; ++i) {
00148 if (i % 2 == 0) {
00149 deque->pushRight(i);
00150 this->inVec.push_back(i);
00151 } else {
00152 deque->pushLeft(i);
00153 this->inVec.push_back(i);
00154 }
00155 }
00156 return NULL;
00157 }
00158 };
00159
00160 template<typename DequeType, typename ParaType, const char * CLASS_NAME>
00161 atomic<ParaType> ThreadPushRight<DequeType, ParaType, CLASS_NAME>::checksum;
00162
00163 template<typename DequeType, typename ParaType, const char * CLASS_NAME>
00164 class ThreadPushRightFactory: public ThreadFactory<ParaType> {
00165 private:
00166 DequeType *deque;
00167 BDequeTest<DequeType, ParaType, CLASS_NAME> *testcase;
00168 public:
00169 ThreadPushRightFactory(DequeType * q, BDequeTest<DequeType, ParaType,
00170 CLASS_NAME> * qt) :
00171 deque(q), testcase(qt) {
00172 }
00173
00174 virtual Runnable ** createThreads(int threadNum, int elementNum,
00175 int operationNum) {
00176 testcase->reset();
00177 deque = testcase->getDeque();
00178
00179 this->inVec.clear();
00180 this->outVec.clear();
00181
00182 ThreadPushRight<DequeType, ParaType, CLASS_NAME>::checksum = 0;
00183
00184 Runnable ** threads;
00185 threads = new Runnable*[threadNum];
00186 for (int i = 0; i < threadNum; ++i)
00187 threads[i]
00188 = new ThreadPushRight<DequeType, ParaType, CLASS_NAME> (deque, testcase, operationNum);
00189
00190 return threads;
00191 }
00192
00193 typedef ThreadPushRight<DequeType, ParaType, CLASS_NAME> ThreadPushRight_T;
00194
00195 virtual void verifyResult(int threadNum, int elementNum) {
00196 while (!deque->empty()) {
00197 ParaType tmp;
00198 if(deque->takeRight(tmp)) {
00199 this->outVec.push_back(tmp);
00200 }
00201 }
00202 cout << this->outVec.size() << endl;
00203 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00204 }
00205
00206 };
00207
00208 template<typename DequeType, typename ParaType, char const* CLASS_NAME>
00209 class Thread4DirFactory: public ThreadFactory<ParaType> {
00210 private:
00211 DequeType *deque;
00212 BDequeTest<DequeType, ParaType, CLASS_NAME> *testcase;
00213
00214 public:
00215 Thread4DirFactory(DequeType * q,
00216 BDequeTest<DequeType, ParaType, CLASS_NAME> * qt) :
00217 deque(q), testcase(qt) {
00218 }
00219
00220 virtual Runnable ** createThreads(int threadNum, int elementNum,
00221 int operationNum) {
00222 testcase->reset();
00223 deque = testcase->getDeque();
00224
00225 this->inVec.clear();
00226 this->outVec.clear();
00227
00228 Thread4Dir<DequeType, ParaType, CLASS_NAME>::checksum = 0;
00229
00230 Runnable ** threads;
00231 threads = new Runnable*[threadNum];
00232 for (int i = 0; i < threadNum; ++i)
00233 threads[i]
00234 = new Thread4Dir<DequeType, ParaType, CLASS_NAME> (deque, testcase, operationNum);
00235
00236 return threads;
00237 }
00238
00239 typedef Thread4Dir<DequeType, ParaType, CLASS_NAME> Thread4Dir_T;
00240 };
00241
00242 template<typename DequeType, typename ParaType, const char * CLASS_NAME>
00243 void BDequeTest<DequeType, ParaType, CLASS_NAME>::testPushRightMT() {
00244 ThreadPushRightFactory<DequeType, ParaType, CLASS_NAME> dequeueFactory(
00245 deque, this);
00246 ThreadRunner::runThreads(&dequeueFactory, CLASS_NAME, "testPushRightMT");
00247 }
00248
00249 template<typename DequeType, typename ParaType, const char * CLASS_NAME>
00250 void BDequeTest<DequeType, ParaType, CLASS_NAME>::test4DirectionMT() {
00251 Thread4DirFactory<DequeType, ParaType, CLASS_NAME> dequeueFactory(deque,
00252 this);
00253 ThreadRunner::runThreads(&dequeueFactory, CLASS_NAME, "testDequeMT");
00254 }
00255
00256 template<typename DequeType, typename ParaType, char const* CLASS_NAME>
00257 class TakeThread: public TestThread<ParaType> {
00258 private:
00259 DequeType *deque;
00260 BDequeTest<DequeType, ParaType, CLASS_NAME> *testcase;
00261 int elementNum;
00262 public:
00263 TakeThread(DequeType * q, BDequeTest<DequeType, ParaType, CLASS_NAME> * qt,
00264 int nElement) :
00265 deque(q), testcase(qt), elementNum(nElement) {
00266 }
00267
00268 void* run() {
00269 for (int i = 0; i < elementNum; ++i) {
00270 if (i % 2 == 0) {
00271 ParaType tmp;
00272 if(deque->takeLeft(tmp)) {
00273 this->outVec.push_back(tmp);
00274 }
00275 } else {
00276 ParaType tmp;
00277 if(deque->takeRight(tmp)) {
00278 this->outVec.push_back(tmp);
00279 }
00280 }
00281 }
00282 return NULL;
00283 }
00284 };
00285
00286 template<typename DequeType, typename ParaType, char const* CLASS_NAME>
00287 class PushThread: public TestThread<ParaType> {
00288 private:
00289 DequeType *deque;
00290 BDequeTest<DequeType, ParaType, CLASS_NAME> *testcase;
00291 int elementNum;
00292 public:
00293 PushThread(DequeType * q, BDequeTest<DequeType, ParaType, CLASS_NAME> * qt,
00294 int nElement) :
00295 deque(q), testcase(qt), elementNum(nElement) {
00296 }
00297
00298 void* run() {
00299 for (int i = 0; i < elementNum; ++i) {
00300 if (i % 2 == 0) {
00301 deque->pushRight(i);
00302 } else {
00303 deque->pushLeft(i);
00304 }
00305 this->inVec.push_back(i);
00306 }
00307 return NULL;
00308 }
00309 };
00310
00311 template<typename DequeType, typename ParaType, const char * CLASS_NAME>
00312 void BDequeTest<DequeType, ParaType, CLASS_NAME>::testProducerConsumer() {
00313 const TestConfig * tc = TestConfig::getInstance();
00314 const vector<int> threadV = tc->getThreadNum();
00315 int elementNum = tc->getElementNum();
00316
00317 typedef TakeThread<DequeType, ParaType, CLASS_NAME> TakeType;
00318 typedef TakeType * pTakeType;
00319 typedef PushThread<DequeType, ParaType, CLASS_NAME> PushType;
00320 typedef PushType * pPushType;
00321
00322 for(unsigned int i=0;i<threadV.size();i++){
00323 int threadN = threadV[i];
00324 pTakeType * takes = new pTakeType[threadN];
00325 pPushType * pushs = new pPushType[threadN];
00326 for(int j=0;j<threadN;j++){
00327 takes[j] = new TakeType(deque, this, elementNum);
00328 pushs[j] = new PushType(deque, this, elementNum);
00329 }
00330
00331 for(int j=0;j<threadN;j++){
00332 takes[j]->start();
00333 pushs[j]->start();
00334 }
00335
00336 for(int j=0;j<threadN;j++){
00337 takes[j]->join();
00338 pushs[j]->join();
00339 }
00340
00341 int sum1 = 0;
00342 int sum2 = 0;
00343 for(int j=0;j<threadN;j++){
00344 sum1+=takes[j]->outVec.size();
00345 sum2+=pushs[j]->inVec.size();
00346 }
00347 CPPUNIT_ASSERT(sum1==sum2);
00348
00349
00350 for(int j=0;j<threadN;j++){
00351 delete takes[j];
00352 delete pushs[j];
00353 }
00354 delete [] takes;
00355 delete [] pushs;
00356 }
00357 }
00358 }
00359 #endif