| Index: base/thread_collision_warner.h
|
| ===================================================================
|
| --- base/thread_collision_warner.h (revision 70342)
|
| +++ base/thread_collision_warner.h (working copy)
|
| @@ -1,243 +0,0 @@
|
| -// Copyright (c) 2008 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_THREAD_COLLISION_WARNER_H_
|
| -#define BASE_THREAD_COLLISION_WARNER_H_
|
| -#pragma once
|
| -
|
| -#include <memory>
|
| -
|
| -#include "base/atomicops.h"
|
| -
|
| -// A helper class alongside macros to be used to verify assumptions about thread
|
| -// safety of a class.
|
| -//
|
| -// Example: Queue implementation non thread-safe but still usable if clients
|
| -// are synchronized somehow.
|
| -//
|
| -// In this case the macro DFAKE_SCOPED_LOCK has to be
|
| -// used, it checks that if a thread is inside the push/pop then
|
| -// noone else is still inside the pop/push
|
| -//
|
| -// class NonThreadSafeQueue {
|
| -// public:
|
| -// ...
|
| -// void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... }
|
| -// int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... }
|
| -// ...
|
| -// private:
|
| -// DFAKE_MUTEX(push_pop_);
|
| -// };
|
| -//
|
| -//
|
| -// Example: Queue implementation non thread-safe but still usable if clients
|
| -// are synchronized somehow, it calls a method to "protect" from
|
| -// a "protected" method
|
| -//
|
| -// In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK
|
| -// has to be used, it checks that if a thread is inside the push/pop
|
| -// then noone else is still inside the pop/push
|
| -//
|
| -// class NonThreadSafeQueue {
|
| -// public:
|
| -// void push(int) {
|
| -// DFAKE_SCOPED_LOCK(push_pop_);
|
| -// ...
|
| -// }
|
| -// int pop() {
|
| -// DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
|
| -// bar();
|
| -// ...
|
| -// }
|
| -// void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... }
|
| -// ...
|
| -// private:
|
| -// DFAKE_MUTEX(push_pop_);
|
| -// };
|
| -//
|
| -//
|
| -// Example: Queue implementation not usable even if clients are synchronized,
|
| -// so only one thread in the class life cycle can use the two members
|
| -// push/pop.
|
| -//
|
| -// In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the
|
| -// specified
|
| -// critical section the first time a thread enters push or pop, from
|
| -// that time on only that thread is allowed to execute push or pop.
|
| -//
|
| -// class NonThreadSafeQueue {
|
| -// public:
|
| -// ...
|
| -// void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
|
| -// int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
|
| -// ...
|
| -// private:
|
| -// DFAKE_MUTEX(push_pop_);
|
| -// };
|
| -//
|
| -//
|
| -// Example: Class that has to be contructed/destroyed on same thread, it has
|
| -// a "shareable" method (with external syncronization) and a not
|
| -// shareable method (even with external synchronization).
|
| -//
|
| -// In this case 3 Critical sections have to be defined
|
| -//
|
| -// class ExoticClass {
|
| -// public:
|
| -// ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
|
| -// ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
|
| -//
|
| -// void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... }
|
| -// void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
|
| -// ...
|
| -// private:
|
| -// DFAKE_MUTEX(ctor_dtor_);
|
| -// DFAKE_MUTEX(shareable_section_);
|
| -// };
|
| -
|
| -
|
| -#if !defined(NDEBUG)
|
| -
|
| -// Defines a class member that acts like a mutex. It is used only as a
|
| -// verification tool.
|
| -#define DFAKE_MUTEX(obj) \
|
| - mutable base::ThreadCollisionWarner obj
|
| -// Asserts the call is never called simultaneously in two threads. Used at
|
| -// member function scope.
|
| -#define DFAKE_SCOPED_LOCK(obj) \
|
| - base::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj)
|
| -// Asserts the call is never called simultaneously in two threads. Used at
|
| -// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks.
|
| -#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \
|
| - base::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj)
|
| -// Asserts the code is always executed in the same thread.
|
| -#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \
|
| - base::ThreadCollisionWarner::Check check_##obj(&obj)
|
| -
|
| -#else
|
| -
|
| -#define DFAKE_MUTEX(obj)
|
| -#define DFAKE_SCOPED_LOCK(obj) ((void)0)
|
| -#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0)
|
| -#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0)
|
| -
|
| -#endif
|
| -
|
| -namespace base {
|
| -
|
| -// The class ThreadCollisionWarner uses an Asserter to notify the collision
|
| -// AsserterBase is the interfaces and DCheckAsserter is the default asserter
|
| -// used. During the unit tests is used another class that doesn't "DCHECK"
|
| -// in case of collision (check thread_collision_warner_unittests.cc)
|
| -struct AsserterBase {
|
| - virtual ~AsserterBase() {}
|
| - virtual void warn() = 0;
|
| -};
|
| -
|
| -struct DCheckAsserter : public AsserterBase {
|
| - virtual ~DCheckAsserter() {}
|
| - virtual void warn();
|
| -};
|
| -
|
| -class ThreadCollisionWarner {
|
| - public:
|
| - // The parameter asserter is there only for test purpose
|
| - ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter())
|
| - : valid_thread_id_(0),
|
| - counter_(0),
|
| - asserter_(asserter) {}
|
| -
|
| - ~ThreadCollisionWarner() {
|
| - delete asserter_;
|
| - }
|
| -
|
| - // This class is meant to be used through the macro
|
| - // DFAKE_SCOPED_LOCK_THREAD_LOCKED
|
| - // it doesn't leave the critical section, as opposed to ScopedCheck,
|
| - // because the critical section being pinned is allowed to be used only
|
| - // from one thread
|
| - class Check {
|
| - public:
|
| - explicit Check(ThreadCollisionWarner* warner)
|
| - : warner_(warner) {
|
| - warner_->EnterSelf();
|
| - }
|
| -
|
| - ~Check() {}
|
| -
|
| - private:
|
| - ThreadCollisionWarner* warner_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Check);
|
| - };
|
| -
|
| - // This class is meant to be used through the macro
|
| - // DFAKE_SCOPED_LOCK
|
| - class ScopedCheck {
|
| - public:
|
| - explicit ScopedCheck(ThreadCollisionWarner* warner)
|
| - : warner_(warner) {
|
| - warner_->Enter();
|
| - }
|
| -
|
| - ~ScopedCheck() {
|
| - warner_->Leave();
|
| - }
|
| -
|
| - private:
|
| - ThreadCollisionWarner* warner_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
|
| - };
|
| -
|
| - // This class is meant to be used through the macro
|
| - // DFAKE_SCOPED_RECURSIVE_LOCK
|
| - class ScopedRecursiveCheck {
|
| - public:
|
| - explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner)
|
| - : warner_(warner) {
|
| - warner_->EnterSelf();
|
| - }
|
| -
|
| - ~ScopedRecursiveCheck() {
|
| - warner_->Leave();
|
| - }
|
| -
|
| - private:
|
| - ThreadCollisionWarner* warner_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ScopedRecursiveCheck);
|
| - };
|
| -
|
| - private:
|
| - // This method stores the current thread identifier and does a DCHECK
|
| - // if a another thread has already done it, it is safe if same thread
|
| - // calls this multiple time (recursion allowed).
|
| - void EnterSelf();
|
| -
|
| - // Same as EnterSelf but recursion is not allowed.
|
| - void Enter();
|
| -
|
| - // Removes the thread_id stored in order to allow other threads to
|
| - // call EnterSelf or Enter.
|
| - void Leave();
|
| -
|
| - // This stores the thread id that is inside the critical section, if the
|
| - // value is 0 then no thread is inside.
|
| - volatile subtle::Atomic32 valid_thread_id_;
|
| -
|
| - // Counter to trace how many time a critical section was "pinned"
|
| - // (when allowed) in order to unpin it when counter_ reaches 0.
|
| - volatile subtle::Atomic32 counter_;
|
| -
|
| - // Here only for class unit tests purpose, during the test I need to not
|
| - // DCHECK but notify the collision with something else.
|
| - AsserterBase* asserter_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ThreadCollisionWarner);
|
| -};
|
| -
|
| -} // namespace base
|
| -
|
| -#endif // BASE_THREAD_COLLISION_WARNER_H_
|
|
|