Torque3D Documentation / _generateds / threadSafeDequeTest.cpp

threadSafeDequeTest.cpp

Engine/source/platform/threads/test/threadSafeDequeTest.cpp

More...

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