Index: base/win/object_watcher.cc |
diff --git a/base/win/object_watcher.cc b/base/win/object_watcher.cc |
index 9a7eea2b054eb85afbc31b5977a549670ba4b2d1..4df54a45d6bf90b5286da96e93dcf674653c2d68 100644 |
--- a/base/win/object_watcher.cc |
+++ b/base/win/object_watcher.cc |
@@ -6,14 +6,19 @@ |
#include "base/bind.h" |
#include "base/logging.h" |
-#include "base/threading/thread_task_runner_handle.h" |
namespace base { |
namespace win { |
//----------------------------------------------------------------------------- |
-ObjectWatcher::ObjectWatcher() : weak_factory_(this) {} |
+ObjectWatcher::ObjectWatcher() |
+ : object_(NULL), |
+ wait_object_(NULL), |
+ origin_loop_(NULL), |
+ run_once_(true), |
+ weak_factory_(this) { |
+} |
ObjectWatcher::~ObjectWatcher() { |
StopWatching(); |
@@ -33,7 +38,7 @@ |
return false; |
// Make sure ObjectWatcher is used in a single-threaded fashion. |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ 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. |
@@ -42,12 +47,16 @@ |
return false; |
} |
- Reset(); |
+ weak_factory_.InvalidateWeakPtrs(); |
+ object_ = NULL; |
+ wait_object_ = NULL; |
+ |
+ origin_loop_->RemoveDestructionObserver(this); |
return true; |
} |
bool ObjectWatcher::IsWatching() const { |
- return object_ != nullptr; |
+ return object_ != NULL; |
} |
HANDLE ObjectWatcher::GetWatchedObject() const { |
@@ -61,18 +70,22 @@ |
// 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->task_runner_->PostTask(FROM_HERE, that->callback_); |
+ 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) { |
- DCHECK(delegate); |
- DCHECK(!wait_object_) << "Already watching an object"; |
- DCHECK(ThreadTaskRunnerHandle::IsSet()); |
+ CHECK(delegate); |
+ if (wait_object_) { |
+ NOTREACHED() << "Already watching an object"; |
+ return false; |
+ } |
- task_runner_ = ThreadTaskRunnerHandle::Get(); |
+ origin_loop_ = MessageLoop::current(); |
+ if (!origin_loop_) |
+ return false; |
run_once_ = execute_only_once; |
@@ -84,17 +97,21 @@ |
// DoneWaiting can be synchronously called from RegisterWaitForSingleObject, |
// so set up all state now. |
- callback_ = |
- Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(), delegate); |
+ callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(), |
+ delegate); |
object_ = object; |
if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting, |
this, INFINITE, wait_flags)) { |
DPLOG(FATAL) << "RegisterWaitForSingleObject failed"; |
- Reset(); |
+ 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. |
+ origin_loop_->AddDestructionObserver(this); |
return true; |
} |
@@ -108,13 +125,10 @@ |
delegate->OnObjectSignaled(object); |
} |
-void ObjectWatcher::Reset() { |
- callback_.Reset(); |
- object_ = nullptr; |
- wait_object_ = nullptr; |
- task_runner_ = nullptr; |
- run_once_ = true; |
- weak_factory_.InvalidateWeakPtrs(); |
+void ObjectWatcher::WillDestroyCurrentMessageLoop() { |
+ // Need to shutdown the watch so that we don't try to access the MessageLoop |
+ // after this point. |
+ StopWatching(); |
} |
} // namespace win |