| // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "base/synchronization/waitable_event_watcher.h" | 
 |  | 
 | #include "base/compiler_specific.h" | 
 | #include "base/synchronization/waitable_event.h" | 
 | #include "base/win/object_watcher.h" | 
 |  | 
 | #include <windows.h> | 
 |  | 
 | namespace base { | 
 |  | 
 | WaitableEventWatcher::WaitableEventWatcher() = default; | 
 |  | 
 | WaitableEventWatcher::~WaitableEventWatcher() {} | 
 |  | 
 | bool WaitableEventWatcher::StartWatching( | 
 |     WaitableEvent* event, | 
 |     EventCallback callback, | 
 |     scoped_refptr<SequencedTaskRunner> task_runner) { | 
 |   DCHECK(event); | 
 |   callback_ = std::move(callback); | 
 |   event_ = event; | 
 |  | 
 |   // Duplicate and hold the event handle until a callback is returned or | 
 |   // waiting is stopped. | 
 |   HANDLE handle = nullptr; | 
 |   if (!::DuplicateHandle(::GetCurrentProcess(),  // hSourceProcessHandle | 
 |                          event->handle(), | 
 |                          ::GetCurrentProcess(),  // hTargetProcessHandle | 
 |                          &handle, | 
 |                          0,      // dwDesiredAccess ignored due to SAME_ACCESS | 
 |                          FALSE,  // !bInheritHandle | 
 |                          DUPLICATE_SAME_ACCESS)) { | 
 |     return false; | 
 |   } | 
 |   duplicated_event_handle_.Set(handle); | 
 |   return watcher_.StartWatchingOnce(handle, this); | 
 | } | 
 |  | 
 | void WaitableEventWatcher::StopWatching() { | 
 |   callback_.Reset(); | 
 |   event_ = NULL; | 
 |   watcher_.StopWatching(); | 
 |   duplicated_event_handle_.Close(); | 
 | } | 
 |  | 
 | void WaitableEventWatcher::OnObjectSignaled(HANDLE h) { | 
 |   DCHECK_EQ(duplicated_event_handle_.Get(), h); | 
 |   WaitableEvent* event = event_; | 
 |   EventCallback callback = std::move(callback_); | 
 |   event_ = NULL; | 
 |   duplicated_event_handle_.Close(); | 
 |   DCHECK(event); | 
 |  | 
 |   std::move(callback).Run(event); | 
 | } | 
 |  | 
 | }  // namespace base |