1*2f083884Ss.makeev_local // The MIT License (MIT) 2*2f083884Ss.makeev_local // 3*2f083884Ss.makeev_local // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 4*2f083884Ss.makeev_local // 5*2f083884Ss.makeev_local // Permission is hereby granted, free of charge, to any person obtaining a copy 6*2f083884Ss.makeev_local // of this software and associated documentation files (the "Software"), to deal 7*2f083884Ss.makeev_local // in the Software without restriction, including without limitation the rights 8*2f083884Ss.makeev_local // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9*2f083884Ss.makeev_local // copies of the Software, and to permit persons to whom the Software is 10*2f083884Ss.makeev_local // furnished to do so, subject to the following conditions: 11*2f083884Ss.makeev_local // 12*2f083884Ss.makeev_local // The above copyright notice and this permission notice shall be included in 13*2f083884Ss.makeev_local // all copies or substantial portions of the Software. 14*2f083884Ss.makeev_local // 15*2f083884Ss.makeev_local // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*2f083884Ss.makeev_local // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*2f083884Ss.makeev_local // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18*2f083884Ss.makeev_local // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*2f083884Ss.makeev_local // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20*2f083884Ss.makeev_local // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21*2f083884Ss.makeev_local // THE SOFTWARE. 22*2f083884Ss.makeev_local 23*2f083884Ss.makeev_local #include "Tests.h" 24*2f083884Ss.makeev_local #include <UnitTest++.h> 25*2f083884Ss.makeev_local #include <MTScheduler.h> 26*2f083884Ss.makeev_local 27*2f083884Ss.makeev_local SUITE(PlatformTests) 28*2f083884Ss.makeev_local { 29*2f083884Ss.makeev_local static const intptr_t DATA_VALUE = 13; 30*2f083884Ss.makeev_local 31*2f083884Ss.makeev_local intptr_t g_Variable = 0; 32*2f083884Ss.makeev_local 33*2f083884Ss.makeev_local void MyThreadFunc(void* userData) 34*2f083884Ss.makeev_local { 35*2f083884Ss.makeev_local intptr_t data = (intptr_t)userData; 36*2f083884Ss.makeev_local 37*2f083884Ss.makeev_local CHECK(data == DATA_VALUE); 38*2f083884Ss.makeev_local 39*2f083884Ss.makeev_local g_Variable = data; 40*2f083884Ss.makeev_local } 41*2f083884Ss.makeev_local 42*2f083884Ss.makeev_local TEST(ThreadTest) 43*2f083884Ss.makeev_local { 44*2f083884Ss.makeev_local intptr_t data = DATA_VALUE; 45*2f083884Ss.makeev_local 46*2f083884Ss.makeev_local MT::Thread thread; 47*2f083884Ss.makeev_local thread.Start(32768, MyThreadFunc, (void*)data); 48*2f083884Ss.makeev_local thread.Join(); 49*2f083884Ss.makeev_local 50*2f083884Ss.makeev_local CHECK(g_Variable == DATA_VALUE); 51*2f083884Ss.makeev_local } 52*2f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53*2f083884Ss.makeev_local 54*2f083884Ss.makeev_local MT::Event *pEvent1 = nullptr; 55*2f083884Ss.makeev_local MT::Event *pEvent2 = nullptr; 56*2f083884Ss.makeev_local 57*2f083884Ss.makeev_local void MyThreadFunc2(void*) 58*2f083884Ss.makeev_local { 59*2f083884Ss.makeev_local MT::Thread::SpinSleepMilliSeconds(300); 60*2f083884Ss.makeev_local pEvent1->Signal(); 61*2f083884Ss.makeev_local } 62*2f083884Ss.makeev_local 63*2f083884Ss.makeev_local TEST(EventTest) 64*2f083884Ss.makeev_local { 65*2f083884Ss.makeev_local MT::Event event1; 66*2f083884Ss.makeev_local event1.Create(MT::EventReset::MANUAL, false); 67*2f083884Ss.makeev_local pEvent1 = &event1; 68*2f083884Ss.makeev_local 69*2f083884Ss.makeev_local MT::Event event2; 70*2f083884Ss.makeev_local event2.Create(MT::EventReset::AUTOMATIC, false); 71*2f083884Ss.makeev_local pEvent2 = &event2; 72*2f083884Ss.makeev_local 73*2f083884Ss.makeev_local MT::Thread thread; 74*2f083884Ss.makeev_local thread.Start(32768, MyThreadFunc2, nullptr); 75*2f083884Ss.makeev_local 76*2f083884Ss.makeev_local bool res0 = event1.Wait(100); 77*2f083884Ss.makeev_local bool res1 = event1.Wait(1000); 78*2f083884Ss.makeev_local bool res2 = event1.Wait(1000); 79*2f083884Ss.makeev_local event1.Reset(); 80*2f083884Ss.makeev_local bool res3 = event1.Wait(100); 81*2f083884Ss.makeev_local 82*2f083884Ss.makeev_local CHECK(!res0); 83*2f083884Ss.makeev_local CHECK(res1); 84*2f083884Ss.makeev_local CHECK(res2); 85*2f083884Ss.makeev_local CHECK(!res3); 86*2f083884Ss.makeev_local 87*2f083884Ss.makeev_local bool res4 = event2.Wait(100); 88*2f083884Ss.makeev_local CHECK(!res4); 89*2f083884Ss.makeev_local bool res5 = event2.Wait(100); 90*2f083884Ss.makeev_local CHECK(!res5); 91*2f083884Ss.makeev_local bool res6 = event2.Wait(100); 92*2f083884Ss.makeev_local CHECK(!res6); 93*2f083884Ss.makeev_local 94*2f083884Ss.makeev_local thread.Join(); 95*2f083884Ss.makeev_local } 96*2f083884Ss.makeev_local 97*2f083884Ss.makeev_local 98*2f083884Ss.makeev_local 99*2f083884Ss.makeev_local MT::AtomicPtrBase<MT::Event> pStressEvent = { nullptr }; 100*2f083884Ss.makeev_local MT::Atomic32Base<uint32> needExitSignal = { 0 }; 101*2f083884Ss.makeev_local MT::Atomic32Base<uint32> needExitWait = { 0 }; 102*2f083884Ss.makeev_local 103*2f083884Ss.makeev_local void EventStressTestSignalThreadFunc(void*) 104*2f083884Ss.makeev_local { 105*2f083884Ss.makeev_local while (needExitSignal.Load() == 0) 106*2f083884Ss.makeev_local { 107*2f083884Ss.makeev_local MT::Thread::SpinSleepMicroSeconds(50); 108*2f083884Ss.makeev_local MT::Event * pEvent = pStressEvent.Load(); 109*2f083884Ss.makeev_local pEvent->Signal(); 110*2f083884Ss.makeev_local } 111*2f083884Ss.makeev_local } 112*2f083884Ss.makeev_local 113*2f083884Ss.makeev_local void EventStressTestWaitThreadFunc(void*) 114*2f083884Ss.makeev_local { 115*2f083884Ss.makeev_local while (needExitWait.Load() == 0) 116*2f083884Ss.makeev_local { 117*2f083884Ss.makeev_local MT::Event * pEvent = pStressEvent.Load(); 118*2f083884Ss.makeev_local bool res = pEvent->Wait(100); 119*2f083884Ss.makeev_local CHECK(res == true); 120*2f083884Ss.makeev_local } 121*2f083884Ss.makeev_local } 122*2f083884Ss.makeev_local 123*2f083884Ss.makeev_local 124*2f083884Ss.makeev_local 125*2f083884Ss.makeev_local 126*2f083884Ss.makeev_local TEST(EventStressTest) 127*2f083884Ss.makeev_local { 128*2f083884Ss.makeev_local MT::Event stressEvent; 129*2f083884Ss.makeev_local stressEvent.Create(MT::EventReset::AUTOMATIC, false); 130*2f083884Ss.makeev_local pStressEvent.Store( &stressEvent ); 131*2f083884Ss.makeev_local 132*2f083884Ss.makeev_local needExitSignal.Store(0); 133*2f083884Ss.makeev_local needExitWait.Store(0); 134*2f083884Ss.makeev_local 135*2f083884Ss.makeev_local MT::Thread signalThreads[6]; 136*2f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(signalThreads); i++) 137*2f083884Ss.makeev_local { 138*2f083884Ss.makeev_local signalThreads[i].Start(32768, EventStressTestSignalThreadFunc, nullptr); 139*2f083884Ss.makeev_local } 140*2f083884Ss.makeev_local 141*2f083884Ss.makeev_local MT::Thread waitThreads[2]; 142*2f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(waitThreads); i++) 143*2f083884Ss.makeev_local { 144*2f083884Ss.makeev_local waitThreads[i].Start(32768, EventStressTestWaitThreadFunc, nullptr); 145*2f083884Ss.makeev_local } 146*2f083884Ss.makeev_local 147*2f083884Ss.makeev_local 148*2f083884Ss.makeev_local 149*2f083884Ss.makeev_local int64 startTime = MT::GetTimeMicroSeconds(); 150*2f083884Ss.makeev_local 151*2f083884Ss.makeev_local const int iterationsCount = 5000; 152*2f083884Ss.makeev_local for(int i = 0; i < iterationsCount; i++) 153*2f083884Ss.makeev_local { 154*2f083884Ss.makeev_local bool res = stressEvent.Wait(100); 155*2f083884Ss.makeev_local CHECK(res == true); 156*2f083884Ss.makeev_local } 157*2f083884Ss.makeev_local 158*2f083884Ss.makeev_local int64 endTime = MT::GetTimeMicroSeconds(); 159*2f083884Ss.makeev_local 160*2f083884Ss.makeev_local int microSecondsPerWait = (int)((endTime - startTime) / (int64)iterationsCount); 161*2f083884Ss.makeev_local 162*2f083884Ss.makeev_local printf("microseconds per wait = %d iterations(%d)\n", microSecondsPerWait, iterationsCount); 163*2f083884Ss.makeev_local 164*2f083884Ss.makeev_local needExitWait.Store(1); 165*2f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(waitThreads); i++) 166*2f083884Ss.makeev_local { 167*2f083884Ss.makeev_local waitThreads[i].Join(); 168*2f083884Ss.makeev_local } 169*2f083884Ss.makeev_local 170*2f083884Ss.makeev_local MT::Thread::Sleep(100); 171*2f083884Ss.makeev_local 172*2f083884Ss.makeev_local needExitSignal.Store(1); 173*2f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(signalThreads); i++) 174*2f083884Ss.makeev_local { 175*2f083884Ss.makeev_local signalThreads[i].Join(); 176*2f083884Ss.makeev_local } 177*2f083884Ss.makeev_local 178*2f083884Ss.makeev_local bool res = stressEvent.Wait(300); 179*2f083884Ss.makeev_local CHECK(res == true); 180*2f083884Ss.makeev_local 181*2f083884Ss.makeev_local res = stressEvent.Wait(300); 182*2f083884Ss.makeev_local CHECK(res == false); 183*2f083884Ss.makeev_local 184*2f083884Ss.makeev_local 185*2f083884Ss.makeev_local } 186*2f083884Ss.makeev_local 187*2f083884Ss.makeev_local 188*2f083884Ss.makeev_local TEST(SleepTest) 189*2f083884Ss.makeev_local { 190*2f083884Ss.makeev_local 191*2f083884Ss.makeev_local MT::Timer timer; 192*2f083884Ss.makeev_local 193*2f083884Ss.makeev_local MT::Thread::SpinSleepMilliSeconds(100); 194*2f083884Ss.makeev_local 195*2f083884Ss.makeev_local CHECK( timer.GetPastMilliSeconds() >= 100 ); 196*2f083884Ss.makeev_local } 197*2f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 198*2f083884Ss.makeev_local } 199