1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// Copyright (c) 2012 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/win/object_watcher.h"
#include "base/bind.h"
#include "base/logging.h"
namespace base {
namespace win {
//-----------------------------------------------------------------------------
ObjectWatcher::ObjectWatcher()
: object_(NULL),
wait_object_(NULL),
origin_loop_(NULL),
run_once_(true),
weak_factory_(this) {
}
ObjectWatcher::~ObjectWatcher() {
StopWatching();
}
bool ObjectWatcher::StartWatchingOnce(HANDLE object, Delegate* delegate) {
return StartWatchingInternal(object, delegate, true);
}
bool ObjectWatcher::StartWatchingMultipleTimes(HANDLE object,
Delegate* delegate) {
return StartWatchingInternal(object, delegate, false);
}
bool ObjectWatcher::StopWatching() {
if (!wait_object_)
return false;
// Make sure ObjectWatcher is used in a single-threaded fashion.
DCHECK_EQ(origin_loop_, MessageLoop::current());
// Blocking call to cancel the wait. Any callbacks already in progress will
// finish before we return from this call.
if (!UnregisterWaitEx(wait_object_, INVALID_HANDLE_VALUE)) {
DPLOG(FATAL) << "UnregisterWaitEx failed";
return false;
}
weak_factory_.InvalidateWeakPtrs();
object_ = NULL;
wait_object_ = NULL;
MessageLoop::current()->RemoveDestructionObserver(this);
return true;
}
bool ObjectWatcher::IsWatching() const {
return object_ != NULL;
}
HANDLE ObjectWatcher::GetWatchedObject() const {
return object_;
}
// static
void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) {
DCHECK(!timed_out);
// The destructor blocks on any callbacks that are in flight, so we know that
// that is always a pointer to a valid ObjectWater.
ObjectWatcher* that = static_cast<ObjectWatcher*>(param);
that->origin_loop_->task_runner()->PostTask(FROM_HERE, that->callback_);
if (that->run_once_)
that->callback_.Reset();
}
bool ObjectWatcher::StartWatchingInternal(HANDLE object, Delegate* delegate,
bool execute_only_once) {
CHECK(delegate);
if (wait_object_) {
NOTREACHED() << "Already watching an object";
return false;
}
run_once_ = execute_only_once;
// Since our job is to just notice when an object is signaled and report the
// result back to this thread, we can just run on a Windows wait thread.
DWORD wait_flags = WT_EXECUTEINWAITTHREAD;
if (run_once_)
wait_flags |= WT_EXECUTEONLYONCE;
// DoneWaiting can be synchronously called from RegisterWaitForSingleObject,
// so set up all state now.
callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(),
delegate);
object_ = object;
origin_loop_ = MessageLoop::current();
if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting,
this, INFINITE, wait_flags)) {
DPLOG(FATAL) << "RegisterWaitForSingleObject failed";
object_ = NULL;
wait_object_ = NULL;
return false;
}
// We need to know if the current message loop is going away so we can
// prevent the wait thread from trying to access a dead message loop.
MessageLoop::current()->AddDestructionObserver(this);
return true;
}
void ObjectWatcher::Signal(Delegate* delegate) {
// Signaling the delegate may result in our destruction or a nested call to
// StartWatching(). As a result, we save any state we need and clear previous
// watcher state before signaling the delegate.
HANDLE object = object_;
if (run_once_)
StopWatching();
delegate->OnObjectSignaled(object);
}
void ObjectWatcher::WillDestroyCurrentMessageLoop() {
// Need to shutdown the watch so that we don't try to access the MessageLoop
// after this point.
StopWatching();
}
} // namespace win
} // namespace base
|