Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: base/win/object_watcher.cc

Issue 2277333002: Revert of Remove MessageLoop::current() from base::win::ObjectWatcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/win/object_watcher.h ('k') | chrome/common/service_process_util_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/win/object_watcher.h" 5 #include "base/win/object_watcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/threading/thread_task_runner_handle.h"
10 9
11 namespace base { 10 namespace base {
12 namespace win { 11 namespace win {
13 12
14 //----------------------------------------------------------------------------- 13 //-----------------------------------------------------------------------------
15 14
16 ObjectWatcher::ObjectWatcher() : weak_factory_(this) {} 15 ObjectWatcher::ObjectWatcher()
16 : object_(NULL),
17 wait_object_(NULL),
18 origin_loop_(NULL),
19 run_once_(true),
20 weak_factory_(this) {
21 }
17 22
18 ObjectWatcher::~ObjectWatcher() { 23 ObjectWatcher::~ObjectWatcher() {
19 StopWatching(); 24 StopWatching();
20 } 25 }
21 26
22 bool ObjectWatcher::StartWatchingOnce(HANDLE object, Delegate* delegate) { 27 bool ObjectWatcher::StartWatchingOnce(HANDLE object, Delegate* delegate) {
23 return StartWatchingInternal(object, delegate, true); 28 return StartWatchingInternal(object, delegate, true);
24 } 29 }
25 30
26 bool ObjectWatcher::StartWatchingMultipleTimes(HANDLE object, 31 bool ObjectWatcher::StartWatchingMultipleTimes(HANDLE object,
27 Delegate* delegate) { 32 Delegate* delegate) {
28 return StartWatchingInternal(object, delegate, false); 33 return StartWatchingInternal(object, delegate, false);
29 } 34 }
30 35
31 bool ObjectWatcher::StopWatching() { 36 bool ObjectWatcher::StopWatching() {
32 if (!wait_object_) 37 if (!wait_object_)
33 return false; 38 return false;
34 39
35 // Make sure ObjectWatcher is used in a single-threaded fashion. 40 // Make sure ObjectWatcher is used in a single-threaded fashion.
36 DCHECK(task_runner_->BelongsToCurrentThread()); 41 DCHECK_EQ(origin_loop_, MessageLoop::current());
37 42
38 // Blocking call to cancel the wait. Any callbacks already in progress will 43 // Blocking call to cancel the wait. Any callbacks already in progress will
39 // finish before we return from this call. 44 // finish before we return from this call.
40 if (!UnregisterWaitEx(wait_object_, INVALID_HANDLE_VALUE)) { 45 if (!UnregisterWaitEx(wait_object_, INVALID_HANDLE_VALUE)) {
41 DPLOG(FATAL) << "UnregisterWaitEx failed"; 46 DPLOG(FATAL) << "UnregisterWaitEx failed";
42 return false; 47 return false;
43 } 48 }
44 49
45 Reset(); 50 weak_factory_.InvalidateWeakPtrs();
51 object_ = NULL;
52 wait_object_ = NULL;
53
54 origin_loop_->RemoveDestructionObserver(this);
46 return true; 55 return true;
47 } 56 }
48 57
49 bool ObjectWatcher::IsWatching() const { 58 bool ObjectWatcher::IsWatching() const {
50 return object_ != nullptr; 59 return object_ != NULL;
51 } 60 }
52 61
53 HANDLE ObjectWatcher::GetWatchedObject() const { 62 HANDLE ObjectWatcher::GetWatchedObject() const {
54 return object_; 63 return object_;
55 } 64 }
56 65
57 // static 66 // static
58 void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) { 67 void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) {
59 DCHECK(!timed_out); 68 DCHECK(!timed_out);
60 69
61 // The destructor blocks on any callbacks that are in flight, so we know that 70 // The destructor blocks on any callbacks that are in flight, so we know that
62 // that is always a pointer to a valid ObjectWater. 71 // that is always a pointer to a valid ObjectWater.
63 ObjectWatcher* that = static_cast<ObjectWatcher*>(param); 72 ObjectWatcher* that = static_cast<ObjectWatcher*>(param);
64 that->task_runner_->PostTask(FROM_HERE, that->callback_); 73 that->origin_loop_->task_runner()->PostTask(FROM_HERE, that->callback_);
65 if (that->run_once_) 74 if (that->run_once_)
66 that->callback_.Reset(); 75 that->callback_.Reset();
67 } 76 }
68 77
69 bool ObjectWatcher::StartWatchingInternal(HANDLE object, Delegate* delegate, 78 bool ObjectWatcher::StartWatchingInternal(HANDLE object, Delegate* delegate,
70 bool execute_only_once) { 79 bool execute_only_once) {
71 DCHECK(delegate); 80 CHECK(delegate);
72 DCHECK(!wait_object_) << "Already watching an object"; 81 if (wait_object_) {
73 DCHECK(ThreadTaskRunnerHandle::IsSet()); 82 NOTREACHED() << "Already watching an object";
83 return false;
84 }
74 85
75 task_runner_ = ThreadTaskRunnerHandle::Get(); 86 origin_loop_ = MessageLoop::current();
87 if (!origin_loop_)
88 return false;
76 89
77 run_once_ = execute_only_once; 90 run_once_ = execute_only_once;
78 91
79 // Since our job is to just notice when an object is signaled and report the 92 // Since our job is to just notice when an object is signaled and report the
80 // result back to this thread, we can just run on a Windows wait thread. 93 // result back to this thread, we can just run on a Windows wait thread.
81 DWORD wait_flags = WT_EXECUTEINWAITTHREAD; 94 DWORD wait_flags = WT_EXECUTEINWAITTHREAD;
82 if (run_once_) 95 if (run_once_)
83 wait_flags |= WT_EXECUTEONLYONCE; 96 wait_flags |= WT_EXECUTEONLYONCE;
84 97
85 // DoneWaiting can be synchronously called from RegisterWaitForSingleObject, 98 // DoneWaiting can be synchronously called from RegisterWaitForSingleObject,
86 // so set up all state now. 99 // so set up all state now.
87 callback_ = 100 callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(),
88 Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(), delegate); 101 delegate);
89 object_ = object; 102 object_ = object;
90 103
91 if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting, 104 if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting,
92 this, INFINITE, wait_flags)) { 105 this, INFINITE, wait_flags)) {
93 DPLOG(FATAL) << "RegisterWaitForSingleObject failed"; 106 DPLOG(FATAL) << "RegisterWaitForSingleObject failed";
94 Reset(); 107 object_ = NULL;
108 wait_object_ = NULL;
95 return false; 109 return false;
96 } 110 }
97 111
112 // We need to know if the current message loop is going away so we can
113 // prevent the wait thread from trying to access a dead message loop.
114 origin_loop_->AddDestructionObserver(this);
98 return true; 115 return true;
99 } 116 }
100 117
101 void ObjectWatcher::Signal(Delegate* delegate) { 118 void ObjectWatcher::Signal(Delegate* delegate) {
102 // Signaling the delegate may result in our destruction or a nested call to 119 // Signaling the delegate may result in our destruction or a nested call to
103 // StartWatching(). As a result, we save any state we need and clear previous 120 // StartWatching(). As a result, we save any state we need and clear previous
104 // watcher state before signaling the delegate. 121 // watcher state before signaling the delegate.
105 HANDLE object = object_; 122 HANDLE object = object_;
106 if (run_once_) 123 if (run_once_)
107 StopWatching(); 124 StopWatching();
108 delegate->OnObjectSignaled(object); 125 delegate->OnObjectSignaled(object);
109 } 126 }
110 127
111 void ObjectWatcher::Reset() { 128 void ObjectWatcher::WillDestroyCurrentMessageLoop() {
112 callback_.Reset(); 129 // Need to shutdown the watch so that we don't try to access the MessageLoop
113 object_ = nullptr; 130 // after this point.
114 wait_object_ = nullptr; 131 StopWatching();
115 task_runner_ = nullptr;
116 run_once_ = true;
117 weak_factory_.InvalidateWeakPtrs();
118 } 132 }
119 133
120 } // namespace win 134 } // namespace win
121 } // namespace base 135 } // namespace base
OLDNEW
« no previous file with comments | « base/win/object_watcher.h ('k') | chrome/common/service_process_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698