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(WaitableEvent::ResetPolicy::MANUAL,
     19                       WaitableEvent::InitialState::NOT_SIGNALED);
     20 
     21   EXPECT_FALSE(event.IsSignaled());
     22 
     23   event.Signal();
     24   EXPECT_TRUE(event.IsSignaled());
     25   EXPECT_TRUE(event.IsSignaled());
     26 
     27   event.Reset();
     28   EXPECT_FALSE(event.IsSignaled());
     29   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     30 
     31   event.Signal();
     32   event.Wait();
     33   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     34 }
     35 
     36 TEST(WaitableEventTest, AutoBasics) {
     37   WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
     38                       WaitableEvent::InitialState::NOT_SIGNALED);
     39 
     40   EXPECT_FALSE(event.IsSignaled());
     41 
     42   event.Signal();
     43   EXPECT_TRUE(event.IsSignaled());
     44   EXPECT_FALSE(event.IsSignaled());
     45 
     46   event.Reset();
     47   EXPECT_FALSE(event.IsSignaled());
     48   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     49 
     50   event.Signal();
     51   event.Wait();
     52   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     53 
     54   event.Signal();
     55   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     56 }
     57 
     58 TEST(WaitableEventTest, WaitManyShortcut) {
     59   WaitableEvent* ev[5];
     60   for (unsigned i = 0; i < 5; ++i) {
     61     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
     62                               WaitableEvent::InitialState::NOT_SIGNALED);
     63   }
     64 
     65   ev[3]->Signal();
     66   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
     67 
     68   ev[3]->Signal();
     69   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
     70 
     71   ev[4]->Signal();
     72   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
     73 
     74   ev[0]->Signal();
     75   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
     76 
     77   for (unsigned i = 0; i < 5; ++i)
     78     delete ev[i];
     79 }
     80 
     81 class WaitableEventSignaler : public PlatformThread::Delegate {
     82  public:
     83   WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
     84       : delay_(delay),
     85         event_(event) {
     86   }
     87 
     88   void ThreadMain() override {
     89     PlatformThread::Sleep(delay_);
     90     event_->Signal();
     91   }
     92 
     93  private:
     94   const TimeDelta delay_;
     95   WaitableEvent* event_;
     96 };
     97 
     98 // Tests that a WaitableEvent can be safely deleted when |Wait| is done without
     99 // additional synchronization.
    100 TEST(WaitableEventTest, WaitAndDelete) {
    101   WaitableEvent* ev =
    102       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
    103                         WaitableEvent::InitialState::NOT_SIGNALED);
    104 
    105   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
    106   PlatformThreadHandle thread;
    107   PlatformThread::Create(0, &signaler, &thread);
    108 
    109   ev->Wait();
    110   delete ev;
    111 
    112   PlatformThread::Join(thread);
    113 }
    114 
    115 // Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
    116 // without additional synchronization.
    117 TEST(WaitableEventTest, WaitMany) {
    118   WaitableEvent* ev[5];
    119   for (unsigned i = 0; i < 5; ++i) {
    120     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
    121                               WaitableEvent::InitialState::NOT_SIGNALED);
    122   }
    123 
    124   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
    125   PlatformThreadHandle thread;
    126   PlatformThread::Create(0, &signaler, &thread);
    127 
    128   size_t index = WaitableEvent::WaitMany(ev, 5);
    129 
    130   for (unsigned i = 0; i < 5; ++i)
    131     delete ev[i];
    132 
    133   PlatformThread::Join(thread);
    134   EXPECT_EQ(2u, index);
    135 }
    136 
    137 // Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
    138 // a timeout of 0. (crbug.com/465948)
    139 #if defined(OS_POSIX)
    140 // crbug.com/465948 not fixed yet.
    141 #define MAYBE_TimedWait DISABLED_TimedWait
    142 #else
    143 #define MAYBE_TimedWait TimedWait
    144 #endif
    145 TEST(WaitableEventTest, MAYBE_TimedWait) {
    146   WaitableEvent* ev =
    147       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
    148                         WaitableEvent::InitialState::NOT_SIGNALED);
    149 
    150   TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
    151   WaitableEventSignaler signaler(thread_delay, ev);
    152   PlatformThreadHandle thread;
    153   TimeTicks start = TimeTicks::Now();
    154   PlatformThread::Create(0, &signaler, &thread);
    155 
    156   ev->TimedWait(TimeDelta::Max());
    157   EXPECT_GE(TimeTicks::Now() - start, thread_delay);
    158   delete ev;
    159 
    160   PlatformThread::Join(thread);
    161 }
    162 
    163 }  // namespace base
    164