summaryrefslogtreecommitdiffstats
path: root/base/threading
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-01 04:48:49 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-01 04:48:49 +0000
commitc91775096768e4a75b23a910ddc1e33d9412a3be (patch)
treecb807f9b28d88b4950e41d32fbe73a5c81a94c40 /base/threading
parente0eb450f398ae888aa0fbdb7fd3abc072d5846a2 (diff)
downloadchromium_src-c91775096768e4a75b23a910ddc1e33d9412a3be.zip
chromium_src-c91775096768e4a75b23a910ddc1e33d9412a3be.tar.gz
chromium_src-c91775096768e4a75b23a910ddc1e33d9412a3be.tar.bz2
Move non_thread_safe from base to base/threading and into the base namespace.
TEST=it compiles BUG=none Review URL: http://codereview.chromium.org/6005010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70351 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/threading')
-rw-r--r--base/threading/non_thread_safe.cc28
-rw-r--r--base/threading/non_thread_safe.h64
-rw-r--r--base/threading/non_thread_safe_unittest.cc130
3 files changed, 222 insertions, 0 deletions
diff --git a/base/threading/non_thread_safe.cc b/base/threading/non_thread_safe.cc
new file mode 100644
index 0000000..8b41bc0
--- /dev/null
+++ b/base/threading/non_thread_safe.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 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/threading/non_thread_safe.h"
+
+// These checks are only done in debug builds.
+#ifndef NDEBUG
+
+#include "base/logging.h"
+
+namespace base {
+
+NonThreadSafe::~NonThreadSafe() {
+ DCHECK(CalledOnValidThread());
+}
+
+bool NonThreadSafe::CalledOnValidThread() const {
+ return thread_checker_.CalledOnValidThread();
+}
+
+void NonThreadSafe::DetachFromThread() {
+ thread_checker_.DetachFromThread();
+}
+
+} // namespace base
+
+#endif // NDEBUG
diff --git a/base/threading/non_thread_safe.h b/base/threading/non_thread_safe.h
new file mode 100644
index 0000000..868a031
--- /dev/null
+++ b/base/threading/non_thread_safe.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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.
+
+#ifndef BASE_THREADING_NON_THREAD_SAFE_H_
+#define BASE_THREADING_NON_THREAD_SAFE_H_
+#pragma once
+
+#include "base/threading/thread_checker.h"
+
+namespace base {
+
+// A helper class used to help verify that methods of a class are
+// called from the same thread. One can inherit from this class and use
+// CalledOnValidThread() to verify.
+//
+// This is intended to be used with classes that appear to be thread safe, but
+// aren't. For example, a service or a singleton like the preferences system.
+//
+// Example:
+// class MyClass : public base::NonThreadSafe {
+// public:
+// void Foo() {
+// DCHECK(CalledOnValidThread());
+// ... (do stuff) ...
+// }
+// }
+//
+// In Release mode, CalledOnValidThread will always return true.
+//
+#ifndef NDEBUG
+class NonThreadSafe {
+ public:
+ ~NonThreadSafe();
+
+ bool CalledOnValidThread() const;
+
+ protected:
+ // Changes the thread that is checked for in CalledOnValidThread. The next
+ // call to CalledOnValidThread will attach this class to a new thread. It is
+ // up to the NonThreadSafe derived class to decide to expose this or not.
+ // This may be useful when an object may be created on one thread and then
+ // used exclusively on another thread.
+ void DetachFromThread();
+
+ private:
+ ThreadChecker thread_checker_;
+};
+#else
+// Do nothing in release mode.
+class NonThreadSafe {
+ public:
+ bool CalledOnValidThread() const {
+ return true;
+ }
+
+ protected:
+ void DetachFromThread() {}
+};
+#endif // NDEBUG
+
+} // namespace base
+
+#endif // BASE_NON_THREAD_SAFE_H_
diff --git a/base/threading/non_thread_safe_unittest.cc b/base/threading/non_thread_safe_unittest.cc
new file mode 100644
index 0000000..7d158cf
--- /dev/null
+++ b/base/threading/non_thread_safe_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2010 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/basictypes.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/threading/simple_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#ifndef NDEBUG
+
+namespace base {
+
+// Simple class to exersice the basics of NonThreadSafe.
+// Both the destructor and DoStuff should verify that they were
+// called on the same thread as the constructor.
+class NonThreadSafeClass : public NonThreadSafe {
+ public:
+ NonThreadSafeClass() {}
+
+ // Verifies that it was called on the same thread as the constructor.
+ void DoStuff() {
+ DCHECK(CalledOnValidThread());
+ }
+
+ void DetachFromThread() {
+ NonThreadSafe::DetachFromThread();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NonThreadSafeClass);
+};
+
+// Calls NonThreadSafeClass::DoStuff on another thread.
+class CallDoStuffOnThread : public SimpleThread {
+ public:
+ CallDoStuffOnThread(NonThreadSafeClass* non_thread_safe_class)
+ : SimpleThread("call_do_stuff_on_thread"),
+ non_thread_safe_class_(non_thread_safe_class) {
+ }
+
+ virtual void Run() {
+ non_thread_safe_class_->DoStuff();
+ }
+
+ private:
+ NonThreadSafeClass* non_thread_safe_class_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
+};
+
+// Deletes NonThreadSafeClass on a different thread.
+class DeleteNonThreadSafeClassOnThread : public SimpleThread {
+ public:
+ DeleteNonThreadSafeClassOnThread(NonThreadSafeClass* non_thread_safe_class)
+ : SimpleThread("delete_non_thread_safe_class_on_thread"),
+ non_thread_safe_class_(non_thread_safe_class) {
+ }
+
+ virtual void Run() {
+ non_thread_safe_class_.reset();
+ }
+
+ private:
+ scoped_ptr<NonThreadSafeClass> non_thread_safe_class_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteNonThreadSafeClassOnThread);
+};
+
+TEST(NonThreadSafeTest, CallsAllowedOnSameThread) {
+ scoped_ptr<NonThreadSafeClass> non_thread_safe_class(
+ new NonThreadSafeClass);
+
+ // Verify that DoStuff doesn't assert.
+ non_thread_safe_class->DoStuff();
+
+ // Verify that the destructor doesn't assert.
+ non_thread_safe_class.reset();
+}
+
+TEST(NonThreadSafeTest, DetachThenDestructOnDifferentThread) {
+ scoped_ptr<NonThreadSafeClass> non_thread_safe_class(
+ new NonThreadSafeClass);
+
+ // Verify that the destructor doesn't assert when called on a different thread
+ // after a detach.
+ non_thread_safe_class->DetachFromThread();
+ DeleteNonThreadSafeClassOnThread delete_on_thread(
+ non_thread_safe_class.release());
+
+ delete_on_thread.Start();
+ delete_on_thread.Join();
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(NonThreadSafeDeathTest, MethodNotAllowedOnDifferentThread) {
+ ASSERT_DEBUG_DEATH({
+ scoped_ptr<NonThreadSafeClass> non_thread_safe_class(
+ new NonThreadSafeClass);
+
+ // Verify that DoStuff asserts when called on a different thread.
+ CallDoStuffOnThread call_on_thread(non_thread_safe_class.get());
+
+ call_on_thread.Start();
+ call_on_thread.Join();
+ }, "");
+}
+
+TEST(NonThreadSafeDeathTest, DestructorNotAllowedOnDifferentThread) {
+ ASSERT_DEBUG_DEATH({
+ scoped_ptr<NonThreadSafeClass> non_thread_safe_class(
+ new NonThreadSafeClass);
+
+ // Verify that the destructor asserts when called on a different thread.
+ DeleteNonThreadSafeClassOnThread delete_on_thread(
+ non_thread_safe_class.release());
+
+ delete_on_thread.Start();
+ delete_on_thread.Join();
+ }, "");
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace base
+
+#endif // NDEBUG