summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/base/sequence_checker.h
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/chromium/base/sequence_checker.h')
-rw-r--r--security/sandbox/chromium/base/sequence_checker.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/sequence_checker.h b/security/sandbox/chromium/base/sequence_checker.h
new file mode 100644
index 0000000000..60ffd75a4f
--- /dev/null
+++ b/security/sandbox/chromium/base/sequence_checker.h
@@ -0,0 +1,143 @@
+// Copyright (c) 2012 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_SEQUENCE_CHECKER_H_
+#define BASE_SEQUENCE_CHECKER_H_
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/sequence_checker_impl.h"
+#include "base/strings/string_piece.h"
+#include "build/build_config.h"
+
+// SequenceChecker is a helper class used to help verify that some methods of a
+// class are called sequentially (for thread-safety). It supports thread safety
+// annotations (see base/thread_annotations.h).
+//
+// Use the macros below instead of the SequenceChecker directly so that the
+// unused member doesn't result in an extra byte (four when padded) per
+// instance in production.
+//
+// This class is much prefered to ThreadChecker for thread-safety checks.
+// ThreadChecker should only be used for classes that are truly thread-affine
+// (use thread-local-storage or a third-party API that does).
+//
+// Usage:
+// class MyClass {
+// public:
+// MyClass() {
+// // It's sometimes useful to detach on construction for objects that are
+// // constructed in one place and forever after used from another
+// // sequence.
+// DETACH_FROM_SEQUENCE(my_sequence_checker_);
+// }
+//
+// ~MyClass() {
+// // SequenceChecker doesn't automatically check it's destroyed on origin
+// // sequence for the same reason it's sometimes detached in the
+// // constructor. It's okay to destroy off sequence if the owner
+// // otherwise knows usage on the associated sequence is done. If you're
+// // not detaching in the constructor, you probably want to explicitly
+// // check in the destructor.
+// DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+// }
+// void MyMethod() {
+// DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+// ... (do stuff) ...
+// MyOtherMethod();
+// }
+//
+// void MyOtherMethod()
+// VALID_CONTEXT_REQUIRED(my_sequence_checker_) {
+// foo_ = 42;
+// }
+//
+// private:
+// // GUARDED_BY_CONTEXT() enforces that this member is only
+// // accessed from a scope that invokes DCHECK_CALLED_ON_VALID_SEQUENCE()
+// // or from a function annotated with VALID_CONTEXT_REQUIRED(). A
+// // DCHECK build will not compile if the member is accessed and these
+// // conditions are not met.
+// int foo_ GUARDED_BY_CONTEXT(my_sequence_checker_);
+//
+// SEQUENCE_CHECKER(my_sequence_checker_);
+// }
+
+#define SEQUENCE_CHECKER_INTERNAL_CONCAT2(a, b) a##b
+#define SEQUENCE_CHECKER_INTERNAL_CONCAT(a, b) \
+ SEQUENCE_CHECKER_INTERNAL_CONCAT2(a, b)
+#define SEQUENCE_CHECKER_INTERNAL_UID(prefix) \
+ SEQUENCE_CHECKER_INTERNAL_CONCAT(prefix, __LINE__)
+
+#if DCHECK_IS_ON()
+#define SEQUENCE_CHECKER(name) base::SequenceChecker name
+#define DCHECK_CALLED_ON_VALID_SEQUENCE(name, ...) \
+ base::ScopedValidateSequenceChecker SEQUENCE_CHECKER_INTERNAL_UID( \
+ scoped_validate_sequence_checker_)(name, ##__VA_ARGS__);
+#define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence()
+#else // DCHECK_IS_ON()
+#if __OBJC__ && defined(OS_IOS) && !HAS_FEATURE(objc_cxx_static_assert)
+// TODO(thakis): Remove this branch once Xcode's clang has clang r356148.
+#define SEQUENCE_CHECKER(name)
+#else
+#define SEQUENCE_CHECKER(name) static_assert(true, "")
+#endif
+#define DCHECK_CALLED_ON_VALID_SEQUENCE(name, ...) EAT_STREAM_PARAMETERS
+#define DETACH_FROM_SEQUENCE(name)
+#endif // DCHECK_IS_ON()
+
+namespace base {
+
+// Do nothing implementation, for use in release mode.
+//
+// Note: You should almost always use the SequenceChecker class (through the
+// above macros) to get the right version for your build configuration.
+// Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
+// order to support thread_annotations.h.
+class LOCKABLE SequenceCheckerDoNothing {
+ public:
+ SequenceCheckerDoNothing() = default;
+
+ // Moving between matching sequences is allowed to help classes with
+ // SequenceCheckers that want a default move-construct/assign.
+ SequenceCheckerDoNothing(SequenceCheckerDoNothing&& other) = default;
+ SequenceCheckerDoNothing& operator=(SequenceCheckerDoNothing&& other) =
+ default;
+
+ bool CalledOnValidSequence() const WARN_UNUSED_RESULT { return true; }
+ void DetachFromSequence() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SequenceCheckerDoNothing);
+};
+
+#if DCHECK_IS_ON()
+class SequenceChecker : public SequenceCheckerImpl {
+};
+#else
+class SequenceChecker : public SequenceCheckerDoNothing {
+};
+#endif // DCHECK_IS_ON()
+
+class SCOPED_LOCKABLE ScopedValidateSequenceChecker {
+ public:
+ explicit ScopedValidateSequenceChecker(const SequenceChecker& checker)
+ EXCLUSIVE_LOCK_FUNCTION(checker) {
+ DCHECK(checker.CalledOnValidSequence());
+ }
+
+ explicit ScopedValidateSequenceChecker(const SequenceChecker& checker,
+ const StringPiece& msg)
+ EXCLUSIVE_LOCK_FUNCTION(checker) {
+ DCHECK(checker.CalledOnValidSequence()) << msg;
+ }
+
+ ~ScopedValidateSequenceChecker() UNLOCK_FUNCTION() {}
+
+ private:
+};
+
+} // namespace base
+
+#endif // BASE_SEQUENCE_CHECKER_H_