Index: third_party/mojo/src/mojo/edk/system/channel_manager.cc |
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.cc b/third_party/mojo/src/mojo/edk/system/channel_manager.cc |
index 634accc8353b8f07ffbe7388a54b6de6bee16869..a5301b39300810374845c550f38da47e6b88821d 100644 |
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.cc |
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.cc |
@@ -18,27 +18,68 @@ namespace system { |
namespace { |
-void ShutdownChannelHelper(const ChannelInfo& channel_info) { |
- if (base::MessageLoopProxy::current() == |
- channel_info.channel_thread_task_runner) { |
- channel_info.channel->Shutdown(); |
+void ShutdownChannelHelper( |
+ const ChannelInfo& channel_info, |
+ const base::Closure& callback, |
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) { |
+ DCHECK(base::MessageLoopProxy::current() == |
+ channel_info.channel_thread_task_runner); |
+ channel_info.channel->Shutdown(); |
+ if (callback_thread_task_runner) { |
+ bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback); |
+ DCHECK(ok); |
} else { |
- channel_info.channel->WillShutdownSoon(); |
- channel_info.channel_thread_task_runner->PostTask( |
- FROM_HERE, base::Bind(&Channel::Shutdown, channel_info.channel)); |
+ callback.Run(); |
} |
} |
} // namespace |
-ChannelManager::ChannelManager(embedder::PlatformSupport* platform_support) |
- : platform_support_(platform_support) { |
+ChannelManager::ChannelManager( |
+ embedder::PlatformSupport* platform_support, |
+ scoped_refptr<base::TaskRunner> io_thread_task_runner, |
+ ConnectionManager* connection_manager) |
+ : platform_support_(platform_support), |
+ io_thread_task_runner_(io_thread_task_runner), |
+ connection_manager_(connection_manager) { |
+ DCHECK(platform_support_); |
+ DCHECK(io_thread_task_runner_); |
+ // (|connection_manager_| may be null.) |
} |
ChannelManager::~ChannelManager() { |
- // No need to take the lock. |
- for (const auto& map_elem : channel_infos_) |
- ShutdownChannelHelper(map_elem.second); |
+ // |Shutdown()| must be called before destruction and have been completed. |
+ // TODO(vtl): This doesn't verify the above condition very strictly at all |
+ // (e.g., we may never have had any channels, or we may have manually shut all |
+ // the channels down). |
+ DCHECK(channel_infos_.empty()); |
+} |
+ |
+void ChannelManager::ShutdownOnIOThread() { |
+ // Taking this lock really shouldn't be necessary, but we do it for |
+ // consistency. |
+ base::hash_map<ChannelId, ChannelInfo> channel_infos; |
+ { |
+ base::AutoLock locker(lock_); |
+ channel_infos.swap(channel_infos_); |
+ } |
+ |
+ for (const auto& map_elem : channel_infos) { |
+ const ChannelInfo& channel_info = map_elem.second; |
+ DCHECK(base::MessageLoopProxy::current() == |
+ channel_info.channel_thread_task_runner); |
+ channel_info.channel->Shutdown(); |
+ } |
+} |
+ |
+void ChannelManager::Shutdown( |
+ const base::Closure& callback, |
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) { |
+ bool ok = io_thread_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ChannelManager::ShutdownHelper, base::Unretained(this), |
+ callback, callback_thread_task_runner)); |
+ DCHECK(ok); |
} |
scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannelOnIOThread( |
@@ -57,9 +98,10 @@ scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannel( |
ChannelId channel_id, |
embedder::ScopedPlatformHandle platform_handle, |
scoped_refptr<base::TaskRunner> io_thread_task_runner, |
- base::Closure callback, |
+ const base::Closure& callback, |
scoped_refptr<base::TaskRunner> callback_thread_task_runner) { |
- DCHECK(io_thread_task_runner); |
+ // TODO(vtl): Remove |io_thread_task_runner| argument. |
+ DCHECK_EQ(io_thread_task_runner, io_thread_task_runner_); |
DCHECK(!callback.is_null()); |
// (|callback_thread_task_runner| may be null.) |
@@ -67,12 +109,13 @@ scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannel( |
scoped_refptr<system::MessagePipeDispatcher> dispatcher = |
system::MessagePipeDispatcher::CreateRemoteMessagePipe( |
&bootstrap_channel_endpoint); |
- io_thread_task_runner->PostTask( |
+ bool ok = io_thread_task_runner_->PostTask( |
FROM_HERE, |
base::Bind(&ChannelManager::CreateChannelHelper, base::Unretained(this), |
channel_id, base::Passed(&platform_handle), |
bootstrap_channel_endpoint, callback, |
callback_thread_task_runner)); |
+ DCHECK(ok); |
return dispatcher; |
} |
@@ -87,7 +130,24 @@ void ChannelManager::WillShutdownChannel(ChannelId channel_id) { |
GetChannel(channel_id)->WillShutdownSoon(); |
} |
-void ChannelManager::ShutdownChannel(ChannelId channel_id) { |
+void ChannelManager::ShutdownChannelOnIOThread(ChannelId channel_id) { |
+ ChannelInfo channel_info; |
+ { |
+ base::AutoLock locker(lock_); |
+ auto it = channel_infos_.find(channel_id); |
+ DCHECK(it != channel_infos_.end()); |
+ channel_info.Swap(&it->second); |
+ channel_infos_.erase(it); |
+ } |
+ DCHECK(base::MessageLoopProxy::current() == |
+ channel_info.channel_thread_task_runner); |
+ channel_info.channel->Shutdown(); |
+} |
+ |
+void ChannelManager::ShutdownChannel( |
+ ChannelId channel_id, |
+ const base::Closure& callback, |
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) { |
ChannelInfo channel_info; |
{ |
base::AutoLock locker(lock_); |
@@ -96,7 +156,23 @@ void ChannelManager::ShutdownChannel(ChannelId channel_id) { |
channel_info.Swap(&it->second); |
channel_infos_.erase(it); |
} |
- ShutdownChannelHelper(channel_info); |
+ channel_info.channel->WillShutdownSoon(); |
+ bool ok = channel_info.channel_thread_task_runner->PostTask( |
+ FROM_HERE, base::Bind(&ShutdownChannelHelper, channel_info, callback, |
+ callback_thread_task_runner)); |
+ DCHECK(ok); |
+} |
+ |
+void ChannelManager::ShutdownHelper( |
+ const base::Closure& callback, |
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) { |
+ ShutdownOnIOThread(); |
+ if (callback_thread_task_runner) { |
+ bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback); |
+ DCHECK(ok); |
+ } else { |
+ callback.Run(); |
+ } |
} |
void ChannelManager::CreateChannelOnIOThreadHelper( |
@@ -126,14 +202,16 @@ void ChannelManager::CreateChannelHelper( |
ChannelId channel_id, |
embedder::ScopedPlatformHandle platform_handle, |
scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint, |
- base::Closure callback, |
+ const base::Closure& callback, |
scoped_refptr<base::TaskRunner> callback_thread_task_runner) { |
CreateChannelOnIOThreadHelper(channel_id, platform_handle.Pass(), |
bootstrap_channel_endpoint); |
- if (callback_thread_task_runner) |
- callback_thread_task_runner->PostTask(FROM_HERE, callback); |
- else |
+ if (callback_thread_task_runner) { |
+ bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback); |
+ DCHECK(ok); |
+ } else { |
callback.Run(); |
+ } |
} |
} // namespace system |