| OLD | NEW | 
|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "mojo/public/cpp/bindings/sync_handle_registry.h" | 5 #include "mojo/public/cpp/bindings/sync_handle_registry.h" | 
| 6 | 6 | 
| 7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" | 
| 8 #include "base/logging.h" | 8 #include "base/logging.h" | 
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" | 
| 10 #include "base/threading/thread_local.h" | 10 #include "base/threading/thread_local.h" | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 48 void SyncHandleRegistry::UnregisterHandle(const Handle& handle) { | 48 void SyncHandleRegistry::UnregisterHandle(const Handle& handle) { | 
| 49   DCHECK(thread_checker_.CalledOnValidThread()); | 49   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 50   if (!base::ContainsKey(handles_, handle)) | 50   if (!base::ContainsKey(handles_, handle)) | 
| 51     return; | 51     return; | 
| 52 | 52 | 
| 53   MojoResult result = wait_set_.RemoveHandle(handle); | 53   MojoResult result = wait_set_.RemoveHandle(handle); | 
| 54   DCHECK_EQ(MOJO_RESULT_OK, result); | 54   DCHECK_EQ(MOJO_RESULT_OK, result); | 
| 55   handles_.erase(handle); | 55   handles_.erase(handle); | 
| 56 } | 56 } | 
| 57 | 57 | 
| 58 bool SyncHandleRegistry::WatchAllHandles(const bool* should_stop[], | 58 bool SyncHandleRegistry::RegisterEvent(base::WaitableEvent* event, | 
| 59                                          size_t count) { | 59                                        const base::Closure& callback) { | 
|  | 60   auto result = events_.insert({event, callback}); | 
|  | 61   DCHECK(result.second); | 
|  | 62   MojoResult rv = wait_set_.AddEvent(event); | 
|  | 63   if (rv == MOJO_RESULT_OK) | 
|  | 64     return true; | 
|  | 65   DCHECK_EQ(MOJO_RESULT_ALREADY_EXISTS, rv); | 
|  | 66   return false; | 
|  | 67 } | 
|  | 68 | 
|  | 69 void SyncHandleRegistry::UnregisterEvent(base::WaitableEvent* event) { | 
|  | 70   auto it = events_.find(event); | 
|  | 71   DCHECK(it != events_.end()); | 
|  | 72   events_.erase(it); | 
|  | 73   MojoResult rv = wait_set_.RemoveEvent(event); | 
|  | 74   DCHECK_EQ(MOJO_RESULT_OK, rv); | 
|  | 75 } | 
|  | 76 | 
|  | 77 bool SyncHandleRegistry::Wait(const bool* should_stop[], size_t count) { | 
| 60   DCHECK(thread_checker_.CalledOnValidThread()); | 78   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 61 | 79 | 
| 62   size_t num_ready_handles; | 80   size_t num_ready_handles; | 
| 63   Handle ready_handle; | 81   Handle ready_handle; | 
| 64   MojoResult ready_handle_result; | 82   MojoResult ready_handle_result; | 
| 65 | 83 | 
| 66   scoped_refptr<SyncHandleRegistry> preserver(this); | 84   scoped_refptr<SyncHandleRegistry> preserver(this); | 
| 67   while (true) { | 85   while (true) { | 
| 68     for (size_t i = 0; i < count; ++i) | 86     for (size_t i = 0; i < count; ++i) | 
| 69       if (*should_stop[i]) | 87       if (*should_stop[i]) | 
| 70         return true; | 88         return true; | 
| 71 | 89 | 
| 72     // TODO(yzshen): Theoretically it can reduce sync call re-entrancy if we | 90     // TODO(yzshen): Theoretically it can reduce sync call re-entrancy if we | 
| 73     // give priority to the handle that is waiting for sync response. | 91     // give priority to the handle that is waiting for sync response. | 
|  | 92     base::WaitableEvent* ready_event = nullptr; | 
| 74     num_ready_handles = 1; | 93     num_ready_handles = 1; | 
| 75     wait_set_.Wait(&num_ready_handles, &ready_handle, &ready_handle_result); | 94     wait_set_.Wait(&ready_event, &num_ready_handles, &ready_handle, | 
| 76     DCHECK_EQ(1u, num_ready_handles); | 95                    &ready_handle_result); | 
|  | 96     if (num_ready_handles) { | 
|  | 97       DCHECK_EQ(1u, num_ready_handles); | 
|  | 98       const auto iter = handles_.find(ready_handle); | 
|  | 99       iter->second.Run(ready_handle_result); | 
|  | 100     } | 
| 77 | 101 | 
| 78     const auto iter = handles_.find(ready_handle); | 102     if (ready_event) { | 
| 79     iter->second.Run(ready_handle_result); | 103       const auto iter = events_.find(ready_event); | 
|  | 104       DCHECK(iter != events_.end()); | 
|  | 105       iter->second.Run(); | 
|  | 106     } | 
| 80   }; | 107   }; | 
| 81 | 108 | 
| 82   return false; | 109   return false; | 
| 83 } | 110 } | 
| 84 | 111 | 
| 85 SyncHandleRegistry::SyncHandleRegistry() { | 112 SyncHandleRegistry::SyncHandleRegistry() { | 
| 86   DCHECK(!g_current_sync_handle_watcher.Pointer()->Get()); | 113   DCHECK(!g_current_sync_handle_watcher.Pointer()->Get()); | 
| 87   g_current_sync_handle_watcher.Pointer()->Set(this); | 114   g_current_sync_handle_watcher.Pointer()->Set(this); | 
| 88 } | 115 } | 
| 89 | 116 | 
| 90 SyncHandleRegistry::~SyncHandleRegistry() { | 117 SyncHandleRegistry::~SyncHandleRegistry() { | 
| 91   DCHECK(thread_checker_.CalledOnValidThread()); | 118   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 92 | 119 | 
| 93   // This object may be destructed after the thread local storage slot used by | 120   // This object may be destructed after the thread local storage slot used by | 
| 94   // |g_current_sync_handle_watcher| is reset during thread shutdown. | 121   // |g_current_sync_handle_watcher| is reset during thread shutdown. | 
| 95   // For example, another slot in the thread local storage holds a referrence to | 122   // For example, another slot in the thread local storage holds a referrence to | 
| 96   // this object, and that slot is cleaned up after | 123   // this object, and that slot is cleaned up after | 
| 97   // |g_current_sync_handle_watcher|. | 124   // |g_current_sync_handle_watcher|. | 
| 98   if (!g_current_sync_handle_watcher.Pointer()->Get()) | 125   if (!g_current_sync_handle_watcher.Pointer()->Get()) | 
| 99     return; | 126     return; | 
| 100 | 127 | 
| 101   // If this breaks, it is likely that the global variable is bulit into and | 128   // If this breaks, it is likely that the global variable is bulit into and | 
| 102   // accessed from multiple modules. | 129   // accessed from multiple modules. | 
| 103   DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get()); | 130   DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get()); | 
| 104 | 131 | 
| 105   g_current_sync_handle_watcher.Pointer()->Set(nullptr); | 132   g_current_sync_handle_watcher.Pointer()->Set(nullptr); | 
| 106 } | 133 } | 
| 107 | 134 | 
| 108 }  // namespace mojo | 135 }  // namespace mojo | 
| OLD | NEW | 
|---|