Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: cc/layers/delegated_frame_resource_collection_unittest.cc

Issue 47703005: Fix DelegatedFrameResourceCollection thread safety (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/layers/delegated_frame_resource_collection.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/layers/delegated_frame_resource_collection_unittest.cc
diff --git a/cc/layers/delegated_frame_resource_collection_unittest.cc b/cc/layers/delegated_frame_resource_collection_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ecbc7b13652227847f0e5084f70c434704376b33
--- /dev/null
+++ b/cc/layers/delegated_frame_resource_collection_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
+#include "cc/resources/returned_resource.h"
+#include "cc/resources/transferable_resource.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class DelegatedFrameResourceCollectionTest
+ : public testing::Test,
+ public DelegatedFrameResourceCollectionClient {
+ protected:
+ DelegatedFrameResourceCollectionTest() : resources_available_(false) {}
+
+ virtual void SetUp() OVERRIDE { CreateResourceCollection(); }
+
+ virtual void TearDown() OVERRIDE { DestroyResourceCollection(); }
+
+ void CreateResourceCollection() {
+ DCHECK(!resource_collection_);
+ resource_collection_ = new DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+
+ void DestroyResourceCollection() {
+ if (resource_collection_) {
+ resource_collection_->SetClient(NULL);
+ resource_collection_ = NULL;
+ }
+ }
+
+ TransferableResourceArray CreateResourceArray() {
+ TransferableResourceArray resources;
+ TransferableResource resource;
+ resource.id = 444;
+ resources.push_back(resource);
+ return resources;
+ }
+
+ virtual void UnusedResourcesAreAvailable() OVERRIDE {
+ resources_available_ = true;
+ resource_collection_->TakeUnusedResourcesForChildCompositor(
+ &returned_resources_);
+ if (!resources_available_closure_.is_null())
+ resources_available_closure_.Run();
+ }
+
+ bool ReturnAndResetResourcesAvailable() {
+ bool r = resources_available_;
+ resources_available_ = false;
+ return r;
+ }
+
+ scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
+ bool resources_available_;
+ ReturnedResourceArray returned_resources_;
+ base::Closure resources_available_closure_;
+};
+
+// This checks that taking the return callback doesn't take extra refcounts,
+// since it's sent to other threads.
+TEST_F(DelegatedFrameResourceCollectionTest, NoRef) {
+ // Start with one ref.
+ EXPECT_TRUE(resource_collection_->HasOneRef());
+
+ ReturnCallback return_callback =
+ resource_collection_->GetReturnResourcesCallbackForImplThread();
+
+ // Callback shouldn't take a ref since it's sent to other threads.
+ EXPECT_TRUE(resource_collection_->HasOneRef());
+}
+
+void ReturnResourcesOnThread(ReturnCallback callback,
+ const ReturnedResourceArray& resources,
+ base::WaitableEvent* event) {
+ callback.Run(resources);
+ event->Wait();
+}
+
+// Tests that the ReturnCallback can run safely on threads even after the
+// last references to the collection were dropped.
+TEST_F(DelegatedFrameResourceCollectionTest, Thread) {
+ base::Thread thread("test thread");
+ thread.Start();
+
+ TransferableResourceArray resources = CreateResourceArray();
+ resource_collection_->ReceivedResources(resources);
+ resource_collection_->RefResources(resources);
+
+ ReturnedResourceArray returned_resources;
+ TransferableResource::ReturnResources(resources, &returned_resources);
+
+ base::WaitableEvent event(false, false);
+
+ {
+ base::RunLoop run_loop;
+ resources_available_closure_ = run_loop.QuitClosure();
+
+ thread.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &ReturnResourcesOnThread,
+ resource_collection_->GetReturnResourcesCallbackForImplThread(),
+ returned_resources,
+ &event));
+
+ run_loop.Run();
+ }
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, returned_resources_.size());
+ EXPECT_EQ(444u, returned_resources_[0].id);
+ EXPECT_EQ(1, returned_resources_[0].count);
+ returned_resources_.clear();
+
+ // The event prevents the return resources callback from being deleted.
+ // Destroy the last reference from this thread to the collection before
+ // signaling the event, to ensure any reference taken by the callback, if any,
+ // would be the last one.
+ DestroyResourceCollection();
+ event.Signal();
+
+ CreateResourceCollection();
+ resource_collection_->ReceivedResources(resources);
+ resource_collection_->RefResources(resources);
+
+ // Destroy the collection before we have a chance to run the return callback.
+ ReturnCallback return_callback =
+ resource_collection_->GetReturnResourcesCallbackForImplThread();
+ resource_collection_->LoseAllResources();
+ DestroyResourceCollection();
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, returned_resources_.size());
+ EXPECT_EQ(444u, returned_resources_[0].id);
+ EXPECT_EQ(1, returned_resources_[0].count);
+ EXPECT_TRUE(returned_resources_[0].lost);
+ returned_resources_.clear();
+
+ thread.message_loop()->PostTask(FROM_HERE,
+ base::Bind(&ReturnResourcesOnThread,
+ return_callback,
+ returned_resources,
+ &event));
+ event.Signal();
+
+ thread.Stop();
+}
+
+} // namespace
+} // namespace cc
« no previous file with comments | « cc/layers/delegated_frame_resource_collection.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698