12f083884Ss.makeev_local // The MIT License (MIT) 22f083884Ss.makeev_local // 32f083884Ss.makeev_local // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 42f083884Ss.makeev_local // 52f083884Ss.makeev_local // Permission is hereby granted, free of charge, to any person obtaining a copy 62f083884Ss.makeev_local // of this software and associated documentation files (the "Software"), to deal 72f083884Ss.makeev_local // in the Software without restriction, including without limitation the rights 82f083884Ss.makeev_local // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 92f083884Ss.makeev_local // copies of the Software, and to permit persons to whom the Software is 102f083884Ss.makeev_local // furnished to do so, subject to the following conditions: 112f083884Ss.makeev_local // 122f083884Ss.makeev_local // The above copyright notice and this permission notice shall be included in 132f083884Ss.makeev_local // all copies or substantial portions of the Software. 142f083884Ss.makeev_local // 152f083884Ss.makeev_local // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 162f083884Ss.makeev_local // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 172f083884Ss.makeev_local // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 182f083884Ss.makeev_local // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 192f083884Ss.makeev_local // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 202f083884Ss.makeev_local // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 212f083884Ss.makeev_local // THE SOFTWARE. 222f083884Ss.makeev_local 232f083884Ss.makeev_local #include "Tests.h" 242f083884Ss.makeev_local #include <UnitTest++.h> 252f083884Ss.makeev_local #include <MTScheduler.h> 262f083884Ss.makeev_local 272f083884Ss.makeev_local SUITE(PlatformTests) 282f083884Ss.makeev_local { 292f083884Ss.makeev_local static const intptr_t DATA_VALUE = 13; 302f083884Ss.makeev_local 312f083884Ss.makeev_local intptr_t g_Variable = 0; 322f083884Ss.makeev_local 332f083884Ss.makeev_local void MyThreadFunc(void* userData) 342f083884Ss.makeev_local { 352f083884Ss.makeev_local intptr_t data = (intptr_t)userData; 362f083884Ss.makeev_local 372f083884Ss.makeev_local CHECK(data == DATA_VALUE); 382f083884Ss.makeev_local 392f083884Ss.makeev_local g_Variable = data; 402f083884Ss.makeev_local } 412f083884Ss.makeev_local 422f083884Ss.makeev_local TEST(ThreadTest) 432f083884Ss.makeev_local { 442f083884Ss.makeev_local intptr_t data = DATA_VALUE; 452f083884Ss.makeev_local 462f083884Ss.makeev_local MT::Thread thread; 472f083884Ss.makeev_local thread.Start(32768, MyThreadFunc, (void*)data); 482f083884Ss.makeev_local thread.Join(); 492f083884Ss.makeev_local 502f083884Ss.makeev_local CHECK(g_Variable == DATA_VALUE); 512f083884Ss.makeev_local } 522f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 532f083884Ss.makeev_local 542f083884Ss.makeev_local MT::Event *pEvent1 = nullptr; 552f083884Ss.makeev_local MT::Event *pEvent2 = nullptr; 562f083884Ss.makeev_local 572f083884Ss.makeev_local void MyThreadFunc2(void*) 582f083884Ss.makeev_local { 592f083884Ss.makeev_local MT::Thread::SpinSleepMilliSeconds(300); 602f083884Ss.makeev_local pEvent1->Signal(); 612f083884Ss.makeev_local } 622f083884Ss.makeev_local 632f083884Ss.makeev_local TEST(EventTest) 642f083884Ss.makeev_local { 652f083884Ss.makeev_local MT::Event event1; 662f083884Ss.makeev_local event1.Create(MT::EventReset::MANUAL, false); 672f083884Ss.makeev_local pEvent1 = &event1; 682f083884Ss.makeev_local 692f083884Ss.makeev_local MT::Event event2; 702f083884Ss.makeev_local event2.Create(MT::EventReset::AUTOMATIC, false); 712f083884Ss.makeev_local pEvent2 = &event2; 722f083884Ss.makeev_local 732f083884Ss.makeev_local MT::Thread thread; 742f083884Ss.makeev_local thread.Start(32768, MyThreadFunc2, nullptr); 752f083884Ss.makeev_local 762f083884Ss.makeev_local bool res0 = event1.Wait(100); 772f083884Ss.makeev_local bool res1 = event1.Wait(1000); 782f083884Ss.makeev_local bool res2 = event1.Wait(1000); 792f083884Ss.makeev_local event1.Reset(); 802f083884Ss.makeev_local bool res3 = event1.Wait(100); 812f083884Ss.makeev_local 822f083884Ss.makeev_local CHECK(!res0); 832f083884Ss.makeev_local CHECK(res1); 842f083884Ss.makeev_local CHECK(res2); 852f083884Ss.makeev_local CHECK(!res3); 862f083884Ss.makeev_local 872f083884Ss.makeev_local bool res4 = event2.Wait(100); 882f083884Ss.makeev_local CHECK(!res4); 892f083884Ss.makeev_local bool res5 = event2.Wait(100); 902f083884Ss.makeev_local CHECK(!res5); 912f083884Ss.makeev_local bool res6 = event2.Wait(100); 922f083884Ss.makeev_local CHECK(!res6); 932f083884Ss.makeev_local 942f083884Ss.makeev_local thread.Join(); 952f083884Ss.makeev_local } 962f083884Ss.makeev_local 972f083884Ss.makeev_local 982f083884Ss.makeev_local 992f083884Ss.makeev_local MT::AtomicPtrBase<MT::Event> pStressEvent = { nullptr }; 1002f083884Ss.makeev_local MT::Atomic32Base<uint32> needExitSignal = { 0 }; 1012f083884Ss.makeev_local MT::Atomic32Base<uint32> needExitWait = { 0 }; 1022f083884Ss.makeev_local 1032f083884Ss.makeev_local void EventStressTestSignalThreadFunc(void*) 1042f083884Ss.makeev_local { 1052f083884Ss.makeev_local while (needExitSignal.Load() == 0) 1062f083884Ss.makeev_local { 1072f083884Ss.makeev_local MT::Thread::SpinSleepMicroSeconds(50); 1082f083884Ss.makeev_local MT::Event * pEvent = pStressEvent.Load(); 1092f083884Ss.makeev_local pEvent->Signal(); 1102f083884Ss.makeev_local } 1112f083884Ss.makeev_local } 1122f083884Ss.makeev_local 1132f083884Ss.makeev_local void EventStressTestWaitThreadFunc(void*) 1142f083884Ss.makeev_local { 1152f083884Ss.makeev_local while (needExitWait.Load() == 0) 1162f083884Ss.makeev_local { 1172f083884Ss.makeev_local MT::Event * pEvent = pStressEvent.Load(); 118*ea599e92Ss.makeev_local bool res = pEvent->Wait(1000); 1192f083884Ss.makeev_local CHECK(res == true); 1202f083884Ss.makeev_local } 1212f083884Ss.makeev_local } 1222f083884Ss.makeev_local 1232f083884Ss.makeev_local 1242f083884Ss.makeev_local 1252f083884Ss.makeev_local 1262f083884Ss.makeev_local TEST(EventStressTest) 1272f083884Ss.makeev_local { 1282f083884Ss.makeev_local MT::Event stressEvent; 1292f083884Ss.makeev_local stressEvent.Create(MT::EventReset::AUTOMATIC, false); 1302f083884Ss.makeev_local pStressEvent.Store( &stressEvent ); 1312f083884Ss.makeev_local 1322f083884Ss.makeev_local needExitSignal.Store(0); 1332f083884Ss.makeev_local needExitWait.Store(0); 1342f083884Ss.makeev_local 1352f083884Ss.makeev_local MT::Thread signalThreads[6]; 1362f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(signalThreads); i++) 1372f083884Ss.makeev_local { 1382f083884Ss.makeev_local signalThreads[i].Start(32768, EventStressTestSignalThreadFunc, nullptr); 1392f083884Ss.makeev_local } 1402f083884Ss.makeev_local 1412f083884Ss.makeev_local MT::Thread waitThreads[2]; 1422f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(waitThreads); i++) 1432f083884Ss.makeev_local { 1442f083884Ss.makeev_local waitThreads[i].Start(32768, EventStressTestWaitThreadFunc, nullptr); 1452f083884Ss.makeev_local } 1462f083884Ss.makeev_local 1472f083884Ss.makeev_local 1482f083884Ss.makeev_local 1492f083884Ss.makeev_local int64 startTime = MT::GetTimeMicroSeconds(); 1502f083884Ss.makeev_local 1512f083884Ss.makeev_local const int iterationsCount = 5000; 1522f083884Ss.makeev_local for(int i = 0; i < iterationsCount; i++) 1532f083884Ss.makeev_local { 154*ea599e92Ss.makeev_local bool res = stressEvent.Wait(1000); 1552f083884Ss.makeev_local CHECK(res == true); 1562f083884Ss.makeev_local } 1572f083884Ss.makeev_local 1582f083884Ss.makeev_local int64 endTime = MT::GetTimeMicroSeconds(); 1592f083884Ss.makeev_local 1602f083884Ss.makeev_local int microSecondsPerWait = (int)((endTime - startTime) / (int64)iterationsCount); 1612f083884Ss.makeev_local 1622f083884Ss.makeev_local printf("microseconds per wait = %d iterations(%d)\n", microSecondsPerWait, iterationsCount); 1632f083884Ss.makeev_local 1642f083884Ss.makeev_local needExitWait.Store(1); 1652f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(waitThreads); i++) 1662f083884Ss.makeev_local { 1672f083884Ss.makeev_local waitThreads[i].Join(); 1682f083884Ss.makeev_local } 1692f083884Ss.makeev_local 1702f083884Ss.makeev_local MT::Thread::Sleep(100); 1712f083884Ss.makeev_local 1722f083884Ss.makeev_local needExitSignal.Store(1); 1732f083884Ss.makeev_local for(uint32 i = 0; i < MT_ARRAY_SIZE(signalThreads); i++) 1742f083884Ss.makeev_local { 1752f083884Ss.makeev_local signalThreads[i].Join(); 1762f083884Ss.makeev_local } 1772f083884Ss.makeev_local 1782f083884Ss.makeev_local bool res = stressEvent.Wait(300); 1792f083884Ss.makeev_local CHECK(res == true); 1802f083884Ss.makeev_local 1812f083884Ss.makeev_local res = stressEvent.Wait(300); 1822f083884Ss.makeev_local CHECK(res == false); 1832f083884Ss.makeev_local 1842f083884Ss.makeev_local 1852f083884Ss.makeev_local } 1862f083884Ss.makeev_local 1872f083884Ss.makeev_local 1882f083884Ss.makeev_local TEST(SleepTest) 1892f083884Ss.makeev_local { 1902f083884Ss.makeev_local 1912f083884Ss.makeev_local MT::Timer timer; 1922f083884Ss.makeev_local 1932f083884Ss.makeev_local MT::Thread::SpinSleepMilliSeconds(100); 1942f083884Ss.makeev_local 1952f083884Ss.makeev_local CHECK( timer.GetPastMilliSeconds() >= 100 ); 1962f083884Ss.makeev_local } 1972f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1982f083884Ss.makeev_local } 199