From 4324e61da53e9cf22c819b90f3478cbf20bf52b5 Mon Sep 17 00:00:00 2001 From: "scottmg@chromium.org" Date: Thu, 1 Dec 2011 00:01:38 +0000 Subject: Renderer reading side of gamepad The is the glue code that reads from the shared memory buffer on the renderer side. The writer is a background thread the browser. The data here is returned back up into WebKit code via the Chromium port. The writer on the browser side was in this patch: http://codereview.chromium.org/8568029/ And the rest of the related gamepad changes are here: http://codereview.chromium.org/8345027/ BUG=79050 Review URL: http://codereview.chromium.org/8689011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112345 0039d316-1c4b-4281-b951-d872f2087c98 --- content/common/gamepad_seqlock_unittest.cc | 98 ++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 content/common/gamepad_seqlock_unittest.cc (limited to 'content/common/gamepad_seqlock_unittest.cc') diff --git a/content/common/gamepad_seqlock_unittest.cc b/content/common/gamepad_seqlock_unittest.cc new file mode 100644 index 0000000..777d804 --- /dev/null +++ b/content/common/gamepad_seqlock_unittest.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2011 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 "content/common/gamepad_seqlock.h" + +#include + +#include "base/atomic_ref_count.h" +#include "base/threading/platform_thread.h" +#include "base/third_party/dynamic_annotations/dynamic_annotations.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +// Basic test to make sure that basic operation works correctly. + +struct TestData { + unsigned a, b, c; +}; + +class BasicSeqLockTestThread : public PlatformThread::Delegate { + public: + BasicSeqLockTestThread() {} + + void Init( + content::GamepadSeqLock* seqlock, + TestData* data, + base::subtle::Atomic32* ready) { + seqlock_ = seqlock; + data_ = data; + ready_ = ready; + } + virtual void ThreadMain() { + while (AtomicRefCountIsZero(ready_)) { + PlatformThread::YieldCurrentThread(); + } + + for (unsigned i = 0; i < 10000; ++i) { + TestData copy; + base::subtle::Atomic32 version; + do { + version = seqlock_->ReadBegin(); + copy = *data_; + } while (seqlock_->ReadRetry(version)); + + EXPECT_EQ(copy.a + 100, copy.b); + EXPECT_EQ(copy.c, copy.b + copy.a); + } + + AtomicRefCountDec(ready_); + } + + private: + content::GamepadSeqLock* seqlock_; + TestData* data_; + base::AtomicRefCount* ready_; + + DISALLOW_COPY_AND_ASSIGN(BasicSeqLockTestThread); +}; + +TEST(GamepadSeqLockTest, ManyThreads) { + content::GamepadSeqLock seqlock; + TestData data = { 0, 0, 0 }; + base::AtomicRefCount ready = 0; + + ANNOTATE_BENIGN_RACE_SIZED(&data, sizeof(data), "Racey reads are discarded"); + + static const unsigned kNumReaderThreads = 100; + BasicSeqLockTestThread threads[kNumReaderThreads]; + PlatformThreadHandle handles[kNumReaderThreads]; + + for (unsigned i = 0; i < kNumReaderThreads; ++i) + threads[i].Init(&seqlock, &data, &ready); + for (unsigned i = 0; i < kNumReaderThreads; ++i) + ASSERT_TRUE(PlatformThread::Create(0, &threads[i], &handles[i])); + + // The main thread is the writer, and the spawned are readers. + unsigned counter = 0; + for (;;) { + seqlock.WriteBegin(); + data.a = counter++; + data.b = data.a + 100; + data.c = data.b + data.a; + seqlock.WriteEnd(); + + if (counter == 1) + base::AtomicRefCountIncN(&ready, kNumReaderThreads); + + if (AtomicRefCountIsZero(&ready)) + break; + } + + for (unsigned i = 0; i < kNumReaderThreads; ++i) + PlatformThread::Join(handles[i]); +} + +} // namespace base -- cgit v1.1