2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "threads/Event.h"
22 #include "threads/Atomics.h"
24 #include "threads/test/TestHelpers.h"
26 #include <boost/shared_array.hpp>
29 using namespace XbmcThreads;
31 //=============================================================================
33 //=============================================================================
35 class waiter : public IRunnable
41 volatile bool waiting;
43 waiter(CEvent& o, bool& flag) : event(o), result(flag), waiting(false) {}
48 result = event.Wait();
53 class timed_waiter : public IRunnable
56 unsigned int waitTime;
60 volatile bool waiting;
62 timed_waiter(CEvent& o, int& flag, int waitTimeMillis) : event(o), waitTime(waitTimeMillis), result(flag), waiting(false) {}
68 result = event.WaitMSec(waitTime) ? 1 : -1;
73 class group_wait : public IRunnable
81 group_wait(CEventGroup& o) : event(o), timeout(-1), result(NULL), waiting(false) {}
82 group_wait(CEventGroup& o, int timeout_) : event(o), timeout(timeout_), result(NULL), waiting(false) {}
88 result = event.wait();
90 result = event.wait((unsigned int)timeout);
95 //=============================================================================
97 TEST(TestEvent, General)
101 waiter w1(event,result);
102 thread waitThread(w1);
104 EXPECT_TRUE(waitForWaiters(event,1,10000));
106 EXPECT_TRUE(!result);
110 EXPECT_TRUE(waitThread.timed_join(10000));
115 TEST(TestEvent, TwoWaits)
118 bool result1 = false;
119 bool result2 = false;
120 waiter w1(event,result1);
121 waiter w2(event,result2);
122 thread waitThread1(w1);
123 thread waitThread2(w2);
125 EXPECT_TRUE(waitForWaiters(event,2,10000));
127 EXPECT_TRUE(!result1);
128 EXPECT_TRUE(!result2);
132 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
133 EXPECT_TRUE(waitThread2.timed_join(MILLIS(10000)));
135 EXPECT_TRUE(result1);
136 EXPECT_TRUE(result2);
140 TEST(TestEvent, TimedWaits)
144 timed_waiter w1(event,result1,100);
145 thread waitThread1(w1);
147 EXPECT_TRUE(waitForWaiters(event,1,10000));
149 EXPECT_TRUE(result1 == 0);
153 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
155 EXPECT_TRUE(result1 == 1);
158 TEST(TestEvent, TimedWaitsTimeout)
162 timed_waiter w1(event,result1,50);
163 thread waitThread1(w1);
165 EXPECT_TRUE(waitForWaiters(event,1,100));
167 EXPECT_TRUE(result1 == 0);
169 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
171 EXPECT_TRUE(result1 == -1);
174 TEST(TestEvent, Group)
179 CEventGroup group(&event1,&event2,NULL);
181 bool result1 = false;
182 bool result2 = false;
184 waiter w1(event1,result1);
185 waiter w2(event2,result2);
186 group_wait w3(group);
188 thread waitThread1(w1);
189 thread waitThread2(w2);
190 thread waitThread3(w3);
192 EXPECT_TRUE(waitForWaiters(event1,1,10000));
193 EXPECT_TRUE(waitForWaiters(event2,1,10000));
194 EXPECT_TRUE(waitForWaiters(group,1,10000));
196 EXPECT_TRUE(!result1);
197 EXPECT_TRUE(!result2);
199 EXPECT_TRUE(w3.waiting);
200 EXPECT_TRUE(w3.result == NULL);
204 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
205 EXPECT_TRUE(waitThread3.timed_join(MILLIS(10000)));
208 EXPECT_TRUE(result1);
209 EXPECT_TRUE(!w1.waiting);
210 EXPECT_TRUE(!result2);
211 EXPECT_TRUE(w2.waiting);
212 EXPECT_TRUE(!w3.waiting);
213 EXPECT_TRUE(w3.result == &event1);
217 EXPECT_TRUE(waitThread2.timed_join(MILLIS(10000)));
221 TEST(TestEvent, GroupLimitedGroupScope)
227 CEventGroup group(&event1,&event2,NULL);
229 bool result1 = false;
230 bool result2 = false;
232 waiter w1(event1,result1);
233 waiter w2(event2,result2);
234 group_wait w3(group);
236 thread waitThread1(w1);
237 thread waitThread2(w2);
238 thread waitThread3(w3);
240 EXPECT_TRUE(waitForWaiters(event1,1,10000));
241 EXPECT_TRUE(waitForWaiters(event2,1,10000));
242 EXPECT_TRUE(waitForWaiters(group,1,10000));
244 EXPECT_TRUE(!result1);
245 EXPECT_TRUE(!result2);
247 EXPECT_TRUE(w3.waiting);
248 EXPECT_TRUE(w3.result == NULL);
252 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
253 EXPECT_TRUE(waitThread3.timed_join(MILLIS(10000)));
256 EXPECT_TRUE(result1);
257 EXPECT_TRUE(!w1.waiting);
258 EXPECT_TRUE(!result2);
259 EXPECT_TRUE(w2.waiting);
260 EXPECT_TRUE(!w3.waiting);
261 EXPECT_TRUE(w3.result == &event1);
266 SleepMillis(50); // give thread 2 a chance to exit
269 TEST(TestEvent, TwoGroups)
274 CEventGroup group1(2, &event1,&event2);
275 CEventGroup group2(&event1,&event2,NULL);
277 bool result1 = false;
278 bool result2 = false;
280 waiter w1(event1,result1);
281 waiter w2(event2,result2);
282 group_wait w3(group1);
283 group_wait w4(group2);
285 thread waitThread1(w1);
286 thread waitThread2(w2);
287 thread waitThread3(w3);
288 thread waitThread4(w4);
290 EXPECT_TRUE(waitForWaiters(event1,1,10000));
291 EXPECT_TRUE(waitForWaiters(event2,1,10000));
292 EXPECT_TRUE(waitForWaiters(group1,1,10000));
293 EXPECT_TRUE(waitForWaiters(group2,1,10000));
295 EXPECT_TRUE(!result1);
296 EXPECT_TRUE(!result2);
298 EXPECT_TRUE(w3.waiting);
299 EXPECT_EQ(w3.result,(void*)NULL);
300 EXPECT_TRUE(w4.waiting);
301 EXPECT_EQ(w4.result,(void*)NULL);
305 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
306 EXPECT_TRUE(waitThread3.timed_join(MILLIS(10000)));
307 EXPECT_TRUE(waitThread4.timed_join(MILLIS(10000)));
310 EXPECT_TRUE(result1);
311 EXPECT_TRUE(!w1.waiting);
312 EXPECT_TRUE(!result2);
313 EXPECT_TRUE(w2.waiting);
314 EXPECT_TRUE(!w3.waiting);
315 EXPECT_TRUE(w3.result == &event1);
316 EXPECT_TRUE(!w4.waiting);
317 EXPECT_TRUE(w4.result == &event1);
321 EXPECT_TRUE(waitThread2.timed_join(MILLIS(10000)));
324 TEST(TestEvent, AutoResetBehavior)
328 EXPECT_TRUE(!event.WaitMSec(1));
330 event.Set(); // event will remain signaled if there are no waits
332 EXPECT_TRUE(event.WaitMSec(1));
335 TEST(TestEvent, ManualReset)
339 waiter w1(event,result);
340 thread waitThread(w1);
342 EXPECT_TRUE(waitForWaiters(event,1,10000));
344 EXPECT_TRUE(!result);
348 EXPECT_TRUE(waitThread.timed_join(MILLIS(10000)));
352 // with manual reset, the state should remain signaled
353 EXPECT_TRUE(event.WaitMSec(1));
357 EXPECT_TRUE(!event.WaitMSec(1));
360 TEST(TestEvent, InitVal)
362 CEvent event(false,true);
363 EXPECT_TRUE(event.WaitMSec(50));
366 TEST(TestEvent, SimpleTimeout)
369 EXPECT_TRUE(!event.WaitMSec(50));
372 TEST(TestEvent, GroupChildSet)
378 CEventGroup group(&event1,&event2,NULL);
380 bool result1 = false;
381 bool result2 = false;
383 waiter w1(event1,result1);
384 waiter w2(event2,result2);
385 group_wait w3(group);
387 thread waitThread1(w1);
388 thread waitThread2(w2);
389 thread waitThread3(w3);
391 EXPECT_TRUE(waitForWaiters(event2,1,10000));
392 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
393 EXPECT_TRUE(waitThread3.timed_join(MILLIS(10000)));
396 EXPECT_TRUE(result1);
397 EXPECT_TRUE(!result2);
399 EXPECT_TRUE(!w3.waiting);
400 EXPECT_TRUE(w3.result == &event1);
404 EXPECT_TRUE(waitThread2.timed_join(MILLIS(10000)));
407 TEST(TestEvent, GroupChildSet2)
409 CEvent event1(true,true);
412 CEventGroup group(&event1,&event2,NULL);
414 bool result1 = false;
415 bool result2 = false;
417 waiter w1(event1,result1);
418 waiter w2(event2,result2);
419 group_wait w3(group);
421 thread waitThread1(w1);
422 thread waitThread2(w2);
423 thread waitThread3(w3);
425 EXPECT_TRUE(waitForWaiters(event2,1,10000));
426 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
427 EXPECT_TRUE(waitThread3.timed_join(MILLIS(10000)));
430 EXPECT_TRUE(result1);
431 EXPECT_TRUE(!result2);
433 EXPECT_TRUE(!w3.waiting);
434 EXPECT_TRUE(w3.result == &event1);
438 EXPECT_TRUE(waitThread2.timed_join(MILLIS(10000)));
441 TEST(TestEvent, GroupWaitResetsChild)
446 CEventGroup group(&event1,&event2,NULL);
448 group_wait w3(group);
450 thread waitThread3(w3);
452 EXPECT_TRUE(waitForWaiters(group,1,10000));
454 EXPECT_TRUE(w3.waiting);
455 EXPECT_TRUE(w3.result == NULL);
459 EXPECT_TRUE(waitThread3.timed_join(MILLIS(10000)));
461 EXPECT_TRUE(!w3.waiting);
462 EXPECT_TRUE(w3.result == &event2);
463 // event2 should have been reset.
464 EXPECT_TRUE(event2.WaitMSec(1) == false);
467 TEST(TestEvent, GroupTimedWait)
471 CEventGroup group(&event1,&event2,NULL);
473 bool result1 = false;
474 bool result2 = false;
476 waiter w1(event1,result1);
477 waiter w2(event2,result2);
479 thread waitThread1(w1);
480 thread waitThread2(w2);
482 EXPECT_TRUE(waitForWaiters(event1,1,10000));
483 EXPECT_TRUE(waitForWaiters(event2,1,10000));
485 EXPECT_TRUE(group.wait(20) == NULL); // waited ... got nothing
487 group_wait w3(group,50);
488 thread waitThread3(w3);
490 EXPECT_TRUE(waitForWaiters(group,1,10000));
492 EXPECT_TRUE(!result1);
493 EXPECT_TRUE(!result2);
495 EXPECT_TRUE(w3.waiting);
496 EXPECT_TRUE(w3.result == NULL);
498 // this should end given the wait is for only 50 millis
499 EXPECT_TRUE(waitThread3.timed_join(MILLIS(100)));
501 EXPECT_TRUE(!w3.waiting);
502 EXPECT_TRUE(w3.result == NULL);
504 group_wait w4(group,50);
505 thread waitThread4(w4);
507 EXPECT_TRUE(waitForWaiters(group,1,10000));
509 EXPECT_TRUE(w4.waiting);
510 EXPECT_TRUE(w4.result == NULL);
514 EXPECT_TRUE(waitThread1.timed_join(MILLIS(10000)));
515 EXPECT_TRUE(waitThread4.timed_join(MILLIS(10000)));
518 EXPECT_TRUE(result1);
519 EXPECT_TRUE(!result2);
521 EXPECT_TRUE(!w4.waiting);
522 EXPECT_TRUE(w4.result == &event1);
526 EXPECT_TRUE(waitThread2.timed_join(MILLIS(10000)));
529 #define TESTNUM 100000l
530 #define NUMTHREADS 100l
532 CEvent* g_event = NULL;
533 volatile long g_mutex;
535 class mass_waiter : public IRunnable
541 volatile bool waiting;
543 mass_waiter() : event(*g_event), waiting(false) {}
548 AtomicGuard g(&g_mutex);
549 result = event.Wait();
554 class poll_mass_waiter : public IRunnable
560 volatile bool waiting;
562 poll_mass_waiter() : event(*g_event), waiting(false) {}
567 AtomicGuard g(&g_mutex);
568 while ((result = event.WaitMSec(0)) == false);
573 template <class W> void RunMassEventTest(boost::shared_array<W>& m, bool canWaitOnEvent)
575 boost::shared_array<thread> t;
576 t.reset(new thread[NUMTHREADS]);
577 for(size_t i=0; i<NUMTHREADS; i++)
580 EXPECT_TRUE(waitForThread(g_mutex,NUMTHREADS,10000));
583 EXPECT_TRUE(waitForWaiters(*g_event,NUMTHREADS,10000));
586 SleepMillis(100);// give them a little more time
588 for(size_t i=0; i<NUMTHREADS; i++)
590 EXPECT_TRUE(m[i].waiting);
595 for(size_t i=0; i<NUMTHREADS; i++)
597 EXPECT_TRUE(t[i].timed_join(MILLIS(10000)));
600 for(size_t i=0; i<NUMTHREADS; i++)
602 EXPECT_TRUE(!m[i].waiting);
603 EXPECT_TRUE(m[i].result);
608 TEST(TestMassEvent, General)
610 g_event = new CEvent();
612 boost::shared_array<mass_waiter> m;
613 m.reset(new mass_waiter[NUMTHREADS]);
615 RunMassEventTest(m,true);
619 TEST(TestMassEvent, Polling)
621 g_event = new CEvent(true); // polling needs to avoid the auto-reset
623 boost::shared_array<poll_mass_waiter> m;
624 m.reset(new poll_mass_waiter[NUMTHREADS]);
626 RunMassEventTest(m,false);