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 <algorithm>
     10 
     11 #include "base/compiler_specific.h"
     12 #include "base/threading/platform_thread.h"
     13 #include "base/time/time.h"
     14 #include "build/build_config.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace base {
     18 
     19 TEST(WaitableEventTest, ManualBasics) {
     20   WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
     21                       WaitableEvent::InitialState::NOT_SIGNALED);
     22 
     23   EXPECT_FALSE(event.IsSignaled());
     24 
     25   event.Signal();
     26   EXPECT_TRUE(event.IsSignaled());
     27   EXPECT_TRUE(event.IsSignaled());
     28 
     29   event.Reset();
     30   EXPECT_FALSE(event.IsSignaled());
     31   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     32 
     33   event.Signal();
     34   event.Wait();
     35   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     36 }
     37 
     38 TEST(WaitableEventTest, AutoBasics) {
     39   WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
     40                       WaitableEvent::InitialState::NOT_SIGNALED);
     41 
     42   EXPECT_FALSE(event.IsSignaled());
     43 
     44   event.Signal();
     45   EXPECT_TRUE(event.IsSignaled());
     46   EXPECT_FALSE(event.IsSignaled());
     47 
     48   event.Reset();
     49   EXPECT_FALSE(event.IsSignaled());
     50   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     51 
     52   event.Signal();
     53   event.Wait();
     54   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     55 
     56   event.Signal();
     57   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
     58 }
     59 
     60 TEST(WaitableEventTest, WaitManyShortcut) {
     61   WaitableEvent* ev[5];
     62   for (unsigned i = 0; i < 5; ++i) {
     63     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
     64                               WaitableEvent::InitialState::NOT_SIGNALED);
     65   }
     66 
     67   ev[3]->Signal();
     68   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
     69 
     70   ev[3]->Signal();
     71   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
     72 
     73   ev[4]->Signal();
     74   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
     75 
     76   ev[0]->Signal();
     77   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
     78 
     79   for (unsigned i = 0; i < 5; ++i)
     80     delete ev[i];
     81 }
     82 
     83 TEST(WaitableEventTest, WaitManyLeftToRight) {
     84   WaitableEvent* ev[5];
     85   for (size_t i = 0; i < 5; ++i) {
     86     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
     87                               WaitableEvent::InitialState::NOT_SIGNALED);
     88   }
     89 
     90   // Test for consistent left-to-right return behavior across all permutations
     91   // of the input array. This is to verify that only the indices -- and not
     92   // the WaitableEvents' addresses -- are relevant in determining who wins when
     93   // multiple events are signaled.
     94 
     95   std::sort(ev, ev + 5);
     96   do {
     97     ev[0]->Signal();
     98     ev[1]->Signal();
     99     EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
    100 
    101     ev[2]->Signal();
    102     EXPECT_EQ(1u, WaitableEvent::WaitMany(ev, 5));
    103     EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
    104 
    105     ev[3]->Signal();
    106     ev[4]->Signal();
    107     ev[0]->Signal();
    108     EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
    109     EXPECT_EQ(3u, WaitableEvent::WaitMany(ev, 5));
    110     ev[2]->Signal();
    111     EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
    112     EXPECT_EQ(4u, WaitableEvent::WaitMany(ev, 5));
    113   } while (std::next_permutation(ev, ev + 5));
    114 
    115   for (size_t i = 0; i < 5; ++i)
    116     delete ev[i];
    117 }
    118 
    119 class WaitableEventSignaler : public PlatformThread::Delegate {
    120  public:
    121   WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
    122       : delay_(delay),
    123         event_(event) {
    124   }
    125 
    126   void ThreadMain() override {
    127     PlatformThread::Sleep(delay_);
    128     event_->Signal();
    129   }
    130 
    131  private:
    132   const TimeDelta delay_;
    133   WaitableEvent* event_;
    134 };
    135 
    136 // Tests that a WaitableEvent can be safely deleted when |Wait| is done without
    137 // additional synchronization.
    138 TEST(WaitableEventTest, WaitAndDelete) {
    139   WaitableEvent* ev =
    140       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
    141                         WaitableEvent::InitialState::NOT_SIGNALED);
    142 
    143   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
    144   PlatformThreadHandle thread;
    145   PlatformThread::Create(0, &signaler, &thread);
    146 
    147   ev->Wait();
    148   delete ev;
    149 
    150   PlatformThread::Join(thread);
    151 }
    152 
    153 // Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
    154 // without additional synchronization.
    155 TEST(WaitableEventTest, WaitMany) {
    156   WaitableEvent* ev[5];
    157   for (unsigned i = 0; i < 5; ++i) {
    158     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
    159                               WaitableEvent::InitialState::NOT_SIGNALED);
    160   }
    161 
    162   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
    163   PlatformThreadHandle thread;
    164   PlatformThread::Create(0, &signaler, &thread);
    165 
    166   size_t index = WaitableEvent::WaitMany(ev, 5);
    167 
    168   for (unsigned i = 0; i < 5; ++i)
    169     delete ev[i];
    170 
    171   PlatformThread::Join(thread);
    172   EXPECT_EQ(2u, index);
    173 }
    174 
    175 // Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
    176 // a timeout of 0. (crbug.com/465948)
    177 TEST(WaitableEventTest, TimedWait) {
    178   WaitableEvent* ev =
    179       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
    180                         WaitableEvent::InitialState::NOT_SIGNALED);
    181 
    182   TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
    183   WaitableEventSignaler signaler(thread_delay, ev);
    184   PlatformThreadHandle thread;
    185   TimeTicks start = TimeTicks::Now();
    186   PlatformThread::Create(0, &signaler, &thread);
    187 
    188   EXPECT_TRUE(ev->TimedWait(TimeDelta::Max()));
    189   EXPECT_GE(TimeTicks::Now() - start, thread_delay);
    190   delete ev;
    191 
    192   PlatformThread::Join(thread);
    193 }
    194 
    195 // Tests that a sub-ms TimedWait doesn't time out promptly.
    196 TEST(WaitableEventTest, SubMsTimedWait) {
    197   WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
    198                    WaitableEvent::InitialState::NOT_SIGNALED);
    199 
    200   TimeDelta delay = TimeDelta::FromMicroseconds(900);
    201   TimeTicks start_time = TimeTicks::Now();
    202   ev.TimedWait(delay);
    203   EXPECT_GE(TimeTicks::Now() - start_time, delay);
    204 }
    205 
    206 // Tests that TimedWaitUntil can be safely used with various end_time deadline
    207 // values.
    208 TEST(WaitableEventTest, TimedWaitUntil) {
    209   WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
    210                    WaitableEvent::InitialState::NOT_SIGNALED);
    211 
    212   TimeTicks start_time(TimeTicks::Now());
    213   TimeDelta delay = TimeDelta::FromMilliseconds(10);
    214 
    215   // Should be OK to wait for the current time or time in the past.
    216   // That should end promptly and be equivalent to IsSignalled.
    217   EXPECT_FALSE(ev.TimedWaitUntil(start_time));
    218   EXPECT_FALSE(ev.TimedWaitUntil(start_time - delay));
    219 
    220   // Should be OK to wait for zero TimeTicks().
    221   EXPECT_FALSE(ev.TimedWaitUntil(TimeTicks()));
    222 
    223   // Waiting for a time in the future shouldn't end before the deadline
    224   // if the event isn't signalled.
    225   EXPECT_FALSE(ev.TimedWaitUntil(start_time + delay));
    226   EXPECT_GE(TimeTicks::Now() - start_time, delay);
    227 
    228   // Test that passing TimeTicks::Max to TimedWaitUntil is valid and isn't
    229   // the same as passing TimeTicks(). Also verifies that signaling event
    230   // ends the wait promptly.
    231   WaitableEventSignaler signaler(delay, &ev);
    232   PlatformThreadHandle thread;
    233   start_time = TimeTicks::Now();
    234   PlatformThread::Create(0, &signaler, &thread);
    235 
    236   EXPECT_TRUE(ev.TimedWaitUntil(TimeTicks::Max()));
    237   EXPECT_GE(TimeTicks::Now() - start_time, delay);
    238 
    239   PlatformThread::Join(thread);
    240 }
    241 
    242 }  // namespace base
    243