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