15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WaitableEventTest, ManualBasics) {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event(true, false);
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.IsSignaled());
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Signal();
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.IsSignaled());
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.IsSignaled());
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Reset();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.IsSignaled());
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Signal();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Wait();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WaitableEventTest, AutoBasics) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent event(false, false);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.IsSignaled());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Signal();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.IsSignaled());
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.IsSignaled());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Reset();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.IsSignaled());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Signal();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Wait();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Signal();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WaitableEventTest, WaitManyShortcut) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* ev[5];
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < 5; ++i)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ev[i] = new WaitableEvent(false, false);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ev[3]->Signal();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ev[3]->Signal();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ev[4]->Signal();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ev[0]->Signal();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < 5; ++i)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete ev[i];
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WaitableEventSignaler : public PlatformThread::Delegate {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEventSignaler(double seconds, WaitableEvent* ev)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : seconds_(seconds),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ev_(ev) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ThreadMain() OVERRIDE {
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PlatformThread::Sleep(TimeDelta::FromSecondsD(seconds_));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ev_->Signal();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double seconds_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent *const ev_;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(WaitableEventTest, WaitAndDelete) {
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // This test tests that if a WaitableEvent can be safely deleted
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // when |Wait| is done without additional synchrnization.
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If this test crashes, it is a bug.
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WaitableEvent* ev = new WaitableEvent(false, false);
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WaitableEventSignaler signaler(0.01, ev);
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PlatformThreadHandle thread;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PlatformThread::Create(0, &signaler, &thread);
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ev->Wait();
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delete ev;
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PlatformThread::Join(thread);
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WaitableEventTest, WaitMany) {
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // This test tests that if a WaitableEvent can be safely deleted
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // when |WaitMany| is done without additional synchrnization.
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If this test crashes, it is a bug.
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* ev[5];
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < 5; ++i)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ev[i] = new WaitableEvent(false, false);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WaitableEventSignaler signaler(0.01, ev[2]);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlatformThreadHandle thread;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlatformThread::Create(0, &signaler, &thread);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t index = WaitableEvent::WaitMany(ev, 5);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < 5; ++i)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete ev[i];
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PlatformThread::Join(thread);
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(2u, index);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
131