Home | History | Annotate | Download | only in synchronization
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/synchronization/waitable_event.h"
      6 
      7 #include <stddef.h>
      8 
      9 #include "base/compiler_specific.h"
     10 #include "base/threading/platform_thread.h"
     11 #include "base/time/time.h"
     12 #include "build/build_config.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace base {
     16 
     17 TEST(WaitableEventTest, ManualBasics) {
     18   WaitableEvent event(true, false);
     19 
     20   EXPECT_FALSE(event.IsSignaled());
     21 
     22   event.Signal();
     23   EXPECT_TRUE(event.IsSignaled());
     24   EXPECT_TRUE(event.IsSignaled());
     25 
     26   event.Reset();
     27   EXPECT_FALSE(event.IsSignaled());
     28   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     29 
     30   event.Signal();
     31   event.Wait();
     32   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     33 }
     34 
     35 TEST(WaitableEventTest, AutoBasics) {
     36   WaitableEvent event(false, false);
     37 
     38   EXPECT_FALSE(event.IsSignaled());
     39 
     40   event.Signal();
     41   EXPECT_TRUE(event.IsSignaled());
     42   EXPECT_FALSE(event.IsSignaled());
     43 
     44   event.Reset();
     45   EXPECT_FALSE(event.IsSignaled());
     46   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     47 
     48   event.Signal();
     49   event.Wait();
     50   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     51 
     52   event.Signal();
     53   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     54 }
     55 
     56 TEST(WaitableEventTest, WaitManyShortcut) {
     57   WaitableEvent* ev[5];
     58   for (unsigned i = 0; i < 5; ++i)
     59     ev[i] = new WaitableEvent(false, false);
     60 
     61   ev[3]->Signal();
     62   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
     63 
     64   ev[3]->Signal();
     65   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
     66 
     67   ev[4]->Signal();
     68   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
     69 
     70   ev[0]->Signal();
     71   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
     72 
     73   for (unsigned i = 0; i < 5; ++i)
     74     delete ev[i];
     75 }
     76 
     77 class WaitableEventSignaler : public PlatformThread::Delegate {
     78  public:
     79   WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
     80       : delay_(delay),
     81         event_(event) {
     82   }
     83 
     84   void ThreadMain() override {
     85     PlatformThread::Sleep(delay_);
     86     event_->Signal();
     87   }
     88 
     89  private:
     90   const TimeDelta delay_;
     91   WaitableEvent* event_;
     92 };
     93 
     94 // Tests that a WaitableEvent can be safely deleted when |Wait| is done without
     95 // additional synchronization.
     96 TEST(WaitableEventTest, WaitAndDelete) {
     97   WaitableEvent* ev = new WaitableEvent(false, false);
     98 
     99   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
    100   PlatformThreadHandle thread;
    101   PlatformThread::Create(0, &signaler, &thread);
    102 
    103   ev->Wait();
    104   delete ev;
    105 
    106   PlatformThread::Join(thread);
    107 }
    108 
    109 // Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
    110 // without additional synchronization.
    111 TEST(WaitableEventTest, WaitMany) {
    112   WaitableEvent* ev[5];
    113   for (unsigned i = 0; i < 5; ++i)
    114     ev[i] = new WaitableEvent(false, false);
    115 
    116   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
    117   PlatformThreadHandle thread;
    118   PlatformThread::Create(0, &signaler, &thread);
    119 
    120   size_t index = WaitableEvent::WaitMany(ev, 5);
    121 
    122   for (unsigned i = 0; i < 5; ++i)
    123     delete ev[i];
    124 
    125   PlatformThread::Join(thread);
    126   EXPECT_EQ(2u, index);
    127 }
    128 
    129 // Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
    130 // a timeout of 0. (crbug.com/465948)
    131 #if defined(OS_POSIX)
    132 // crbug.com/465948 not fixed yet.
    133 #define MAYBE_TimedWait DISABLED_TimedWait
    134 #else
    135 #define MAYBE_TimedWait TimedWait
    136 #endif
    137 TEST(WaitableEventTest, MAYBE_TimedWait) {
    138   WaitableEvent* ev = new WaitableEvent(false, false);
    139 
    140   TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
    141   WaitableEventSignaler signaler(thread_delay, ev);
    142   PlatformThreadHandle thread;
    143   TimeTicks start = TimeTicks::Now();
    144   PlatformThread::Create(0, &signaler, &thread);
    145 
    146   ev->TimedWait(TimeDelta::Max());
    147   EXPECT_GE(TimeTicks::Now() - start, thread_delay);
    148   delete ev;
    149 
    150   PlatformThread::Join(thread);
    151 }
    152 
    153 }  // namespace base
    154