Index: mojo/public/cpp/bindings/lib/sync_handle_watcher.cc |
diff --git a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc b/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc |
index 13ab4918c915d686f118bdf7aaaf8c521851ca50..a300903a404cfef22f7a07fac4edcd77c0b03563 100644 |
--- a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc |
+++ b/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc |
@@ -4,121 +4,74 @@ |
#include "mojo/public/cpp/bindings/lib/sync_handle_watcher.h" |
-#include "base/lazy_instance.h" |
#include "base/logging.h" |
-#include "base/stl_util.h" |
-#include "base/threading/thread_local.h" |
-#include "mojo/public/c/system/core.h" |
namespace mojo { |
namespace internal { |
-namespace { |
-base::LazyInstance<base::ThreadLocalPointer<SyncHandleWatcher>> |
- g_current_sync_handle_watcher = LAZY_INSTANCE_INITIALIZER; |
+SyncHandleWatcher::SyncHandleWatcher( |
+ const Handle& handle, |
+ MojoHandleSignals handle_signals, |
+ const SyncHandleRegistry::HandleCallback& callback) |
+ : handle_(handle), |
+ handle_signals_(handle_signals), |
+ callback_(callback), |
+ registered_(false), |
+ register_request_count_(0), |
+ destroyed_(new base::RefCountedData<bool>(false)) {} |
-} // namespace |
- |
-// static |
-SyncHandleWatcher* SyncHandleWatcher::current() { |
- SyncHandleWatcher* result = g_current_sync_handle_watcher.Pointer()->Get(); |
- if (!result) { |
- // This object will be destroyed when the current message loop goes away. |
- result = new SyncHandleWatcher(); |
- DCHECK_EQ(result, g_current_sync_handle_watcher.Pointer()->Get()); |
- } |
- return result; |
-} |
- |
-bool SyncHandleWatcher::RegisterHandle(const Handle& handle, |
- MojoHandleSignals handle_signals, |
- const HandleCallback& callback) { |
+SyncHandleWatcher::~SyncHandleWatcher() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (registered_) |
+ SyncHandleRegistry::current()->UnregisterHandle(handle_); |
- if (ContainsKey(handles_, handle)) |
- return false; |
- |
- MojoResult result = MojoAddHandle(wait_set_handle_.get().value(), |
- handle.value(), handle_signals); |
- if (result != MOJO_RESULT_OK) |
- return false; |
- |
- handles_[handle] = callback; |
- return true; |
+ destroyed_->data = true; |
} |
-void SyncHandleWatcher::UnregisterHandle(const Handle& handle) { |
+void SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(ContainsKey(handles_, handle)); |
- |
- MojoResult result = |
- MojoRemoveHandle(wait_set_handle_.get().value(), handle.value()); |
- DCHECK_EQ(MOJO_RESULT_OK, result); |
- |
- handles_.erase(handle); |
+ IncrementRegisterCount(); |
} |
-bool SyncHandleWatcher::WatchAllHandles(const bool* should_stop[], |
- size_t count) { |
+bool SyncHandleWatcher::SyncWatch(const bool* should_stop) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
+ IncrementRegisterCount(); |
+ if (!registered_) { |
+ DecrementRegisterCount(); |
+ return false; |
+ } |
- MojoResult result; |
- uint32_t num_ready_handles; |
- MojoHandle ready_handle; |
- MojoResult ready_handle_result; |
- |
- while (true) { |
- for (size_t i = 0; i < count; ++i) |
- if (*should_stop[i]) |
- return true; |
- do { |
- result = Wait(wait_set_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, |
- MOJO_DEADLINE_INDEFINITE, nullptr); |
- if (result != MOJO_RESULT_OK) |
- return false; |
- |
- // TODO(yzshen): Theoretically it can reduce sync call re-entrancy if we |
- // give priority to the handle that is waiting for sync response. |
- num_ready_handles = 1; |
- result = MojoGetReadyHandles(wait_set_handle_.get().value(), |
- &num_ready_handles, &ready_handle, |
- &ready_handle_result, nullptr); |
- if (result != MOJO_RESULT_OK && result != MOJO_RESULT_SHOULD_WAIT) |
- return false; |
- } while (result == MOJO_RESULT_SHOULD_WAIT); |
- |
- const auto iter = handles_.find(Handle(ready_handle)); |
- iter->second.Run(ready_handle_result); |
- }; |
- |
- return true; |
-} |
- |
-SyncHandleWatcher::SyncHandleWatcher() { |
- MojoHandle handle; |
- MojoResult result = MojoCreateWaitSet(&handle); |
- CHECK_EQ(MOJO_RESULT_OK, result); |
- wait_set_handle_.reset(Handle(handle)); |
- CHECK(wait_set_handle_.is_valid()); |
+ // This object may be destroyed during the WatchAllHandles() call. So we have |
+ // to preserve the boolean that WatchAllHandles uses. |
+ auto destroyed = destroyed_; |
+ const bool* should_stop_array[] = {should_stop, &destroyed->data}; |
+ bool result = |
+ SyncHandleRegistry::current()->WatchAllHandles(should_stop_array, 2); |
- DCHECK(!g_current_sync_handle_watcher.Pointer()->Get()); |
- g_current_sync_handle_watcher.Pointer()->Set(this); |
+ // This object has been destroyed. |
+ if (destroyed->data) |
+ return false; |
- base::MessageLoop::current()->AddDestructionObserver(this); |
+ DecrementRegisterCount(); |
+ return result; |
} |
-SyncHandleWatcher::~SyncHandleWatcher() { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(handles_.empty()); |
- g_current_sync_handle_watcher.Pointer()->Set(nullptr); |
+void SyncHandleWatcher::IncrementRegisterCount() { |
+ register_request_count_++; |
+ if (!registered_ && handle_.is_valid()) { |
Ken Rockot(use gerrit already)
2016/03/26 03:09:26
Is it OK to simply DCHECK that handle_.is_valid()
yzshen1
2016/03/26 06:33:17
I did it this way because I was thinking that it m
|
+ registered_ = SyncHandleRegistry::current()->RegisterHandle( |
+ handle_, handle_signals_, callback_); |
+ } |
} |
-void SyncHandleWatcher::WillDestroyCurrentMessageLoop() { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get()); |
+void SyncHandleWatcher::DecrementRegisterCount() { |
+ DCHECK_GT(register_request_count_, 0u); |
- base::MessageLoop::current()->RemoveDestructionObserver(this); |
- delete this; |
+ register_request_count_--; |
+ if (register_request_count_ == 0 && registered_) { |
+ SyncHandleRegistry::current()->UnregisterHandle(handle_); |
+ registered_ = false; |
+ } |
} |
} // namespace internal |