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