1 // The MIT License (MIT) 2 // 3 // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 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 deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // 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 FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 #include "Tests.h" 24 #include <UnitTest++.h> 25 #include <MTScheduler.h> 26 27 SUITE(PlatformTests) 28 { 29 static const intptr_t DATA_VALUE = 13; 30 31 intptr_t g_Variable = 0; 32 33 void MyThreadFunc(void* userData) 34 { 35 intptr_t data = (intptr_t)userData; 36 37 CHECK(data == DATA_VALUE); 38 39 g_Variable = data; 40 } 41 42 TEST(ThreadTest) 43 { 44 intptr_t data = DATA_VALUE; 45 46 MT::Thread thread; 47 thread.Start(32768, MyThreadFunc, (void*)data); 48 thread.Join(); 49 50 CHECK(g_Variable == DATA_VALUE); 51 } 52 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 54 MT::Event *pEvent1 = nullptr; 55 MT::Event *pEvent2 = nullptr; 56 57 void MyThreadFunc2(void*) 58 { 59 MT::SpinSleepMilliSeconds(300); 60 pEvent1->Signal(); 61 } 62 63 TEST(EventTest) 64 { 65 MT::Event event1; 66 event1.Create(MT::EventReset::MANUAL, false); 67 pEvent1 = &event1; 68 69 MT::Event event2; 70 event2.Create(MT::EventReset::AUTOMATIC, false); 71 pEvent2 = &event2; 72 73 MT::Thread thread; 74 thread.Start(32768, MyThreadFunc2, nullptr); 75 76 bool res0 = event1.Wait(100); 77 bool res1 = event1.Wait(1000); 78 bool res2 = event1.Wait(1000); 79 event1.Reset(); 80 bool res3 = event1.Wait(100); 81 82 CHECK(!res0); 83 CHECK(res1); 84 CHECK(res2); 85 CHECK(!res3); 86 87 bool res4 = event2.Wait(100); 88 CHECK(!res4); 89 bool res5 = event2.Wait(100); 90 CHECK(!res5); 91 bool res6 = event2.Wait(100); 92 CHECK(!res6); 93 94 thread.Join(); 95 } 96 97 98 99 MT::AtomicPtrBase<MT::Event> pStressEvent = { nullptr }; 100 MT::Atomic32Base<uint32> needExitSignal = { 0 }; 101 MT::Atomic32Base<uint32> needExitWait = { 0 }; 102 103 void EventStressTestSignalThreadFunc(void*) 104 { 105 while (needExitSignal.Load() == 0) 106 { 107 MT::SpinSleepMicroSeconds(50); 108 MT::Event * pEvent = pStressEvent.Load(); 109 pEvent->Signal(); 110 } 111 } 112 113 void EventStressTestWaitThreadFunc(void*) 114 { 115 while (needExitWait.Load() == 0) 116 { 117 MT::Event * pEvent = pStressEvent.Load(); 118 bool res = pEvent->Wait(1000); 119 CHECK(res == true); 120 } 121 } 122 123 124 125 126 TEST(EventStressTest) 127 { 128 MT::Event stressEvent; 129 stressEvent.Create(MT::EventReset::AUTOMATIC, false); 130 pStressEvent.Store( &stressEvent ); 131 132 needExitSignal.Store(0); 133 needExitWait.Store(0); 134 135 MT::Thread signalThreads[6]; 136 for(uint32 i = 0; i < MT_ARRAY_SIZE(signalThreads); i++) 137 { 138 signalThreads[i].Start(32768, EventStressTestSignalThreadFunc, nullptr); 139 } 140 141 MT::Thread waitThreads[2]; 142 for(uint32 i = 0; i < MT_ARRAY_SIZE(waitThreads); i++) 143 { 144 waitThreads[i].Start(32768, EventStressTestWaitThreadFunc, nullptr); 145 } 146 147 148 149 int64 startTime = MT::GetTimeMicroSeconds(); 150 151 const int iterationsCount = 5000; 152 for(int i = 0; i < iterationsCount; i++) 153 { 154 bool res = stressEvent.Wait(1000); 155 CHECK(res == true); 156 } 157 158 int64 endTime = MT::GetTimeMicroSeconds(); 159 160 int microSecondsPerWait = (int)((endTime - startTime) / (int64)iterationsCount); 161 162 printf("microseconds per wait = %d iterations(%d)\n", microSecondsPerWait, iterationsCount); 163 164 needExitWait.Store(1); 165 for(uint32 i = 0; i < MT_ARRAY_SIZE(waitThreads); i++) 166 { 167 waitThreads[i].Join(); 168 } 169 170 MT::Thread::Sleep(100); 171 172 needExitSignal.Store(1); 173 for(uint32 i = 0; i < MT_ARRAY_SIZE(signalThreads); i++) 174 { 175 signalThreads[i].Join(); 176 } 177 178 bool res = stressEvent.Wait(300); 179 CHECK(res == true); 180 181 res = stressEvent.Wait(300); 182 CHECK(res == false); 183 184 185 } 186 187 188 TEST(SleepTest) 189 { 190 191 MT::Timer timer; 192 193 MT::SpinSleepMilliSeconds(100); 194 195 CHECK( timer.GetPastMilliSeconds() >= 100 ); 196 } 197 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 198 } 199