summaryrefslogtreecommitdiff
path: root/runtime/scoped_thread_state_change.h
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2015-09-03 16:13:34 -0700
committer Mathieu Chartier <mathieuc@google.com> 2015-09-03 17:33:19 -0700
commitf1d666e1b48f8070ef1177fce156c08827f08eb8 (patch)
tree772cbbe6652b32ea2be31532156295db27579390 /runtime/scoped_thread_state_change.h
parent897ce64153e4758663e464fb5fb339f9a7b496c8 (diff)
Add ScopedThreadSuspension
Fixes the TransitionFromRunnableToSuspended and TransitionFromSuspendedToRunnable pattern that was prone to errors. Change-Id: Ie6ae9c0357c83b4fc4899d05dfa0975553170267
Diffstat (limited to 'runtime/scoped_thread_state_change.h')
-rw-r--r--runtime/scoped_thread_state_change.h28
1 files changed, 26 insertions, 2 deletions
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index b90aa0ec0e..d1cc09ab09 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -31,7 +31,7 @@ namespace art {
// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
// the unchecked variant doesn't aid annotalysis.
-class ScopedThreadStateChange {
+class ScopedThreadStateChange : public ValueObject {
public:
ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE
@@ -102,7 +102,7 @@ class ScopedThreadStateChange {
};
// Assumes we are already runnable.
-class ScopedObjectAccessAlreadyRunnable {
+class ScopedObjectAccessAlreadyRunnable : public ValueObject {
public:
Thread* Self() const {
return self_;
@@ -277,6 +277,30 @@ class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
};
+// Annotalysis helper for going to a suspended state from runnable.
+class ScopedThreadSuspension : public ValueObject {
+ public:
+ explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
+ REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
+ UNLOCK_FUNCTION(Locks::mutator_lock_)
+ ALWAYS_INLINE
+ : self_(self), suspended_state_(suspended_state) {
+ DCHECK(self_ != nullptr);
+ self_->TransitionFromRunnableToSuspended(suspended_state);
+ }
+
+ ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
+ DCHECK_EQ(self_->GetState(), suspended_state_);
+ self_->TransitionFromSuspendedToRunnable();
+ }
+
+ private:
+ Thread* const self_;
+ const ThreadState suspended_state_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
+};
+
+
} // namespace art
#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_