threadSafeDequeTest.cpp
Engine/source/platform/threads/test/threadSafeDequeTest.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2014 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifdef TORQUE_TESTS_ENABLED 25#include "testing/unitTesting.h" 26 27#include "platform/threads/threadSafeDeque.h" 28#include "platform/threads/thread.h" 29#include "core/util/tVector.h" 30#include "console/console.h" 31 32FIXTURE(ThreadSafeDeque) 33{ 34public: 35 // Used by the concurrent test. 36 struct Value : public ThreadSafeRefCount<Value> 37 { 38 U32 mIndex; 39 U32 mTick; 40 41 Value() {} 42 Value(U32 index, U32 tick) 43 : mIndex(index), mTick(tick) {} 44 }; 45 46 typedef ThreadSafeRef<Value> ValueRef; 47 48 struct Deque : public ThreadSafeDeque<ValueRef> 49 { 50 typedef ThreadSafeDeque<ValueRef> Parent; 51 52 U32 mPushIndex; 53 U32 mPopIndex; 54 55 Deque() 56 : mPushIndex(0), mPopIndex(0) {} 57 58 void pushBack(const ValueRef& value) 59 { 60 EXPECT_EQ(value->mIndex, mPushIndex) << "index out of line"; 61 mPushIndex++; 62 Parent::pushBack(value); 63 } 64 65 bool tryPopFront(ValueRef& outValue) 66 { 67 if(Parent::tryPopFront(outValue)) 68 { 69 EXPECT_EQ(outValue->mIndex, mPopIndex) << "index out of line"; 70 mPopIndex++; 71 return true; 72 } 73 else 74 return false; 75 } 76 }; 77 78 struct ProducerThread : public Thread 79 { 80 Vector<U32>& mValues; 81 Deque& mDeque; 82 ProducerThread(Vector<U32>& values, Deque& deque) 83 : mValues(values), mDeque(deque) {} 84 85 virtual void run(void*) 86 { 87 for(U32 i = 0; i < mValues.size(); i++) 88 { 89 U32 tick = Platform::getRealMilliseconds(); 90 mValues[i] = tick; 91 92 ValueRef val = new Value(i, tick); 93 mDeque.pushBack(val); 94 } 95 } 96 }; 97 98 struct ConsumerThread : public Thread 99 { 100 Vector<U32>& mValues; 101 Deque& mDeque; 102 ConsumerThread(Vector<U32>& values, Deque& deque) 103 : mValues(values), mDeque(deque) {} 104 105 virtual void run(void*) 106 { 107 for(U32 i = 0; i < mValues.size(); i++) 108 { 109 ValueRef value; 110 while(!mDeque.tryPopFront(value)); 111 112 EXPECT_EQ(i, value->mIndex); 113 EXPECT_EQ(value->mTick, mValues[i]); 114 } 115 } 116 }; 117}; 118 119// Test deque without concurrency. 120TEST_FIX(ThreadSafeDeque, PopFront) 121{ 122 ThreadSafeDeque<char> deque; 123 String str = "teststring"; 124 125 for(U32 i = 0; i < str.length(); i++) 126 deque.pushBack(str[i]); 127 128 EXPECT_FALSE(deque.isEmpty()); 129 130 char ch; 131 for(U32 i = 0; i < str.length(); i++) 132 { 133 EXPECT_TRUE(deque.tryPopFront(ch)); 134 EXPECT_EQ(str[i], ch); 135 } 136 137 ASSERT_TRUE(deque.isEmpty()); 138} 139 140TEST_FIX(ThreadSafeDeque, PopBack) 141{ 142 ThreadSafeDeque<char> deque; 143 String str = "teststring"; 144 145 const char* p1 = str.c_str() + 4; 146 const char* p2 = p1 + 1; 147 while(*p2) 148 { 149 deque.pushFront(*p1); 150 deque.pushBack(*p2); 151 --p1; 152 ++p2; 153 } 154 155 char ch; 156 for(S32 i = str.length()-1; i >= 0; i--) 157 { 158 EXPECT_TRUE(deque.tryPopBack(ch)); 159 EXPECT_EQ(str[i], ch); 160 } 161 162 ASSERT_TRUE(deque.isEmpty()); 163} 164 165// Test deque in a concurrent setting. 166TEST_FIX(ThreadSafeDeque, Concurrent1) 167{ 168 const U32 NumValues = 100; 169 170 Deque mDeque; 171 Vector<U32> mValues; 172 173 mValues.setSize(NumValues); 174 175 ProducerThread pThread(mValues, mDeque); 176 ConsumerThread cThread(mValues, mDeque); 177 178 pThread.start(); 179 cThread.start(); 180 181 pThread.join(); 182 cThread.join(); 183 184 mValues.clear(); 185}; 186 187#endif 188