Merge "base: add ScopedLockAssertion." am: 3777d9cc10

am: 379b6f403f

Change-Id: I47d1ab2dc1d904e7f22c541232b15ee1ec97aa17
This commit is contained in:
Josh Gao 2019-02-15 18:42:28 -08:00 committed by android-build-merger
commit f01d33b9e8
2 changed files with 43 additions and 14 deletions

View file

@ -52,6 +52,8 @@
#include "fdevent.h"
#include "sysdeps/chrono.h"
using android::base::ScopedLockAssertion;
static void remove_transport(atransport* transport);
static void transport_unref(atransport* transport);
@ -72,17 +74,6 @@ const char* const kFeatureAbb = "abb";
namespace {
// A class that helps the Clang Thread Safety Analysis deal with
// std::unique_lock. Given that std::unique_lock is movable, and the analysis
// can not currently perform alias analysis, it is not annotated. In order to
// assert that the mutex is held, a ScopedAssumeLocked can be created just after
// the std::unique_lock.
class SCOPED_CAPABILITY ScopedAssumeLocked {
public:
ScopedAssumeLocked(std::mutex& mutex) ACQUIRE(mutex) {}
~ScopedAssumeLocked() RELEASE() {}
};
#if ADB_HOST
// Tracks and handles atransport*s that are attempting reconnection.
class ReconnectHandler {
@ -180,7 +171,7 @@ void ReconnectHandler::Run() {
ReconnectAttempt attempt;
{
std::unique_lock<std::mutex> lock(reconnect_mutex_);
ScopedAssumeLocked assume_lock(reconnect_mutex_);
ScopedLockAssertion assume_lock(reconnect_mutex_);
if (!reconnect_queue_.empty()) {
// FIXME: libstdc++ (used on Windows) implements condition_variable with
@ -296,7 +287,7 @@ void BlockingConnectionAdapter::Start() {
LOG(INFO) << this->transport_name_ << ": write thread spawning";
while (true) {
std::unique_lock<std::mutex> lock(mutex_);
ScopedAssumeLocked assume_locked(mutex_);
ScopedLockAssertion assume_locked(mutex_);
cv_.wait(lock, [this]() REQUIRES(mutex_) {
return this->stopped_ || !this->write_queue_.empty();
});
@ -923,7 +914,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, Transp
bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
std::unique_lock<std::mutex> lock(mutex_);
ScopedAssumeLocked assume_locked(mutex_);
ScopedLockAssertion assume_locked(mutex_);
return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
return connection_established_ready_;
}) && connection_established_;

View file

@ -16,6 +16,8 @@
#pragma once
#include <mutex>
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#define CAPABILITY(x) \
@ -104,3 +106,39 @@
#define NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
namespace android {
namespace base {
// A class to help thread safety analysis deal with std::unique_lock and condition_variable.
//
// Clang's thread safety analysis currently doesn't perform alias analysis, so movable types
// like std::unique_lock can't be marked with thread safety annotations. This helper allows
// for manual assertion of lock state in a scope.
//
// For example:
//
// std::mutex mutex;
// std::condition_variable cv;
// std::vector<int> vec GUARDED_BY(mutex);
//
// int pop() {
// std::unique_lock lock(mutex);
// ScopedLockAssertion lock_assertion(mutex);
// cv.wait(lock, []() {
// ScopedLockAssertion lock_assertion(mutex);
// return !vec.empty();
// });
//
// int result = vec.back();
// vec.pop_back();
// return result;
// }
class SCOPED_CAPABILITY ScopedLockAssertion {
public:
ScopedLockAssertion(std::mutex& mutex) ACQUIRE(mutex) {}
~ScopedLockAssertion() RELEASE() {}
};
} // namespace base
} // namespace android