Use single 64bit atomic refcount for Dawn objects

Bug: dawn:105
Change-Id: I7741d5f01579f269db272200d39088c07e2acd92
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7440
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng
2019-05-23 23:55:14 +00:00
committed by Commit Bot service account
parent 34f2fe8a52
commit c391fb7c69
3 changed files with 53 additions and 76 deletions

View File

@@ -13,6 +13,7 @@
// limitations under the License.
#include <gtest/gtest.h>
#include <thread>
#include "dawn_native/RefCounted.h"
@@ -38,8 +39,8 @@ struct RCTest : public RefCounted {
bool* deleted = nullptr;
};
// Test that RCs start with one external ref, and removing it destroys the object.
TEST(RefCounted, StartsWithOneExternalRef) {
// Test that RCs start with one ref, and removing it destroys the object.
TEST(RefCounted, StartsWithOneRef) {
bool deleted = false;
auto test = new RCTest(&deleted);
@@ -47,39 +48,51 @@ TEST(RefCounted, StartsWithOneExternalRef) {
ASSERT_TRUE(deleted);
}
// Test internal refs keep the RC alive.
TEST(RefCounted, InternalRefKeepsAlive) {
// Test adding refs keep the RC alive.
TEST(RefCounted, AddingRefKeepsAlive) {
bool deleted = false;
auto test = new RCTest(&deleted);
test->ReferenceInternal();
test->Release();
ASSERT_FALSE(deleted);
test->ReleaseInternal();
ASSERT_TRUE(deleted);
}
// Test that when adding an external ref from 0, an internal ref is added
TEST(RefCounted, AddExternalRefFromZero) {
bool deleted = false;
auto test = new RCTest(&deleted);
test->ReferenceInternal();
test->Release();
ASSERT_FALSE(deleted);
// Reference adds an internal ref and release removes one
test->Reference();
test->Release();
ASSERT_FALSE(deleted);
test->ReleaseInternal();
test->Release();
ASSERT_TRUE(deleted);
}
// Test Ref remove internal reference when going out of scope
TEST(Ref, EndOfScopeRemovesInternalRef) {
// Test that Reference and Release atomically change the refcount.
TEST(RefCounted, RaceOnReferenceRelease) {
bool deleted = false;
auto* test = new RCTest(&deleted);
auto referenceManyTimes = [test]() {
for (uint32_t i = 0; i < 100000; ++i) {
test->Reference();
}
};
std::thread t1(referenceManyTimes);
std::thread t2(referenceManyTimes);
t1.join();
t2.join();
ASSERT_EQ(test->GetRefCount(), 200001u);
auto releaseManyTimes = [test]() {
for (uint32_t i = 0; i < 100000; ++i) {
test->Release();
}
};
std::thread t3(releaseManyTimes);
std::thread t4(releaseManyTimes);
t3.join();
t4.join();
ASSERT_EQ(test->GetRefCount(), 1u);
}
// Test Ref remove reference when going out of scope
TEST(Ref, EndOfScopeRemovesRef) {
bool deleted = false;
{
Ref<RCTest> test(new RCTest(&deleted));