Index: gpu/ipc/service/gpu_channel_manager.cc |
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc |
index 49cfe2cc8e3c52b94f1563fe4294d63fc7d0f41a..47d4aee8cd345e2fd866cb363c9f8e2d45fdd7ba 100644 |
--- a/gpu/ipc/service/gpu_channel_manager.cc |
+++ b/gpu/ipc/service/gpu_channel_manager.cc |
@@ -40,6 +40,9 @@ const int kMaxGpuIdleTimeMs = 40; |
const int kMaxKeepAliveTimeMs = 200; |
#endif |
+// The maximum amount of time we will spend deleting channels before yielding |
+// to other tasks. |
+const int kMaxChannelDeleterRuntimeS = 1; |
} |
GpuChannelManager::GpuChannelManager( |
@@ -113,9 +116,38 @@ GpuChannelManager::framebuffer_completeness_cache() { |
return framebuffer_completeness_cache_.get(); |
} |
+void GpuChannelManager::RunChannelDeleter() { |
+ base::TimeTicks timeout = |
+ base::TimeTicks::Now() + |
+ base::TimeDelta::FromSeconds(kMaxChannelDeleterRuntimeS); |
+ |
+ for (; pending_deleters_.size() > 0; pending_deleters_.pop()) { |
+ if (!pending_deleters_.front()->DeleteWithTimeout(timeout)) { |
+ // If DeleteWithTimeout returns false, the timeout was reached |
+ // before deletion completed. We should not continue deleting. |
+ break; |
+ } |
+ } |
+ |
+ if (pending_deleters_.size() > 0) { |
+ task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&GpuChannelManager::RunChannelDeleter, |
+ weak_factory_.GetWeakPtr())); |
+ } else { |
+ channel_deleter_running_ = false; |
+ } |
+} |
+ |
void GpuChannelManager::RemoveChannel(int client_id) { |
delegate_->DidDestroyChannel(client_id); |
- gpu_channels_.erase(client_id); |
+ pending_deleters_.emplace( |
+ new GpuChannelDeleter(gpu_channels_.take_and_erase(client_id))); |
+ if (!channel_deleter_running_) { |
+ channel_deleter_running_ = true; |
+ task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&GpuChannelManager::RunChannelDeleter, |
+ weak_factory_.GetWeakPtr())); |
+ } |
} |
GpuChannel* GpuChannelManager::LookupChannel(int32_t client_id) const { |