Merge "base: add ScopedLockAssertion."
This commit is contained in:
commit
3777d9cc10
2 changed files with 43 additions and 14 deletions
|
|
@ -52,6 +52,8 @@
|
||||||
#include "fdevent.h"
|
#include "fdevent.h"
|
||||||
#include "sysdeps/chrono.h"
|
#include "sysdeps/chrono.h"
|
||||||
|
|
||||||
|
using android::base::ScopedLockAssertion;
|
||||||
|
|
||||||
static void remove_transport(atransport* transport);
|
static void remove_transport(atransport* transport);
|
||||||
static void transport_unref(atransport* transport);
|
static void transport_unref(atransport* transport);
|
||||||
|
|
||||||
|
|
@ -72,17 +74,6 @@ const char* const kFeatureAbb = "abb";
|
||||||
|
|
||||||
namespace {
|
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
|
#if ADB_HOST
|
||||||
// Tracks and handles atransport*s that are attempting reconnection.
|
// Tracks and handles atransport*s that are attempting reconnection.
|
||||||
class ReconnectHandler {
|
class ReconnectHandler {
|
||||||
|
|
@ -180,7 +171,7 @@ void ReconnectHandler::Run() {
|
||||||
ReconnectAttempt attempt;
|
ReconnectAttempt attempt;
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(reconnect_mutex_);
|
std::unique_lock<std::mutex> lock(reconnect_mutex_);
|
||||||
ScopedAssumeLocked assume_lock(reconnect_mutex_);
|
ScopedLockAssertion assume_lock(reconnect_mutex_);
|
||||||
|
|
||||||
if (!reconnect_queue_.empty()) {
|
if (!reconnect_queue_.empty()) {
|
||||||
// FIXME: libstdc++ (used on Windows) implements condition_variable with
|
// FIXME: libstdc++ (used on Windows) implements condition_variable with
|
||||||
|
|
@ -296,7 +287,7 @@ void BlockingConnectionAdapter::Start() {
|
||||||
LOG(INFO) << this->transport_name_ << ": write thread spawning";
|
LOG(INFO) << this->transport_name_ << ": write thread spawning";
|
||||||
while (true) {
|
while (true) {
|
||||||
std::unique_lock<std::mutex> lock(mutex_);
|
std::unique_lock<std::mutex> lock(mutex_);
|
||||||
ScopedAssumeLocked assume_locked(mutex_);
|
ScopedLockAssertion assume_locked(mutex_);
|
||||||
cv_.wait(lock, [this]() REQUIRES(mutex_) {
|
cv_.wait(lock, [this]() REQUIRES(mutex_) {
|
||||||
return this->stopped_ || !this->write_queue_.empty();
|
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) {
|
bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
|
||||||
std::unique_lock<std::mutex> lock(mutex_);
|
std::unique_lock<std::mutex> lock(mutex_);
|
||||||
ScopedAssumeLocked assume_locked(mutex_);
|
ScopedLockAssertion assume_locked(mutex_);
|
||||||
return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
|
return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
|
||||||
return connection_established_ready_;
|
return connection_established_ready_;
|
||||||
}) && connection_established_;
|
}) && connection_established_;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||||
|
|
||||||
#define CAPABILITY(x) \
|
#define CAPABILITY(x) \
|
||||||
|
|
@ -104,3 +106,39 @@
|
||||||
|
|
||||||
#define NO_THREAD_SAFETY_ANALYSIS \
|
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||||
THREAD_ANNOTATION_ATTRIBUTE__(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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue