Index: content/child/shared_memory_data_consumer_handle.cc |
diff --git a/content/child/shared_memory_data_consumer_handle.cc b/content/child/shared_memory_data_consumer_handle.cc |
index f11435ada87c22572379c59ce9b80f2e50c85b44..7bf404a5281e2884dc031534fb89343cb0e4db89 100644 |
--- a/content/child/shared_memory_data_consumer_handle.cc |
+++ b/content/child/shared_memory_data_consumer_handle.cc |
@@ -46,6 +46,8 @@ class DelegateThreadSafeReceivedData final |
using Result = blink::WebDataConsumerHandle::Result; |
+// All methods (except for ctor/dtor) must be called with |lock_| aquired |
+// unless otherwise stated. |
class SharedMemoryDataConsumerHandle::Context final |
: public base::RefCountedThreadSafe<Context> { |
public: |
@@ -59,8 +61,12 @@ class SharedMemoryDataConsumerHandle::Context final |
is_handle_active_(true), |
is_two_phase_read_in_progress_(false) {} |
- bool IsEmpty() const { return queue_.empty(); } |
+ bool IsEmpty() const { |
+ lock_.AssertAcquired(); |
+ return queue_.empty(); |
+ } |
void ClearIfNecessary() { |
+ lock_.AssertAcquired(); |
if (!is_handle_locked() && !is_handle_active()) { |
// No one is interested in the contents. |
if (is_on_reader_detached_valid_) { |
@@ -73,20 +79,35 @@ class SharedMemoryDataConsumerHandle::Context final |
} |
} |
void ClearQueue() { |
+ lock_.AssertAcquired(); |
for (auto& data : queue_) { |
delete data; |
} |
queue_.clear(); |
first_offset_ = 0; |
} |
- RequestPeer::ThreadSafeReceivedData* Top() { return queue_.front(); } |
+ RequestPeer::ThreadSafeReceivedData* Top() { |
+ lock_.AssertAcquired(); |
+ return queue_.front(); |
+ } |
void Push(scoped_ptr<RequestPeer::ThreadSafeReceivedData> data) { |
+ lock_.AssertAcquired(); |
queue_.push_back(data.release()); |
} |
- size_t first_offset() const { return first_offset_; } |
- Result result() const { return result_; } |
- void set_result(Result r) { result_ = r; } |
+ size_t first_offset() const { |
+ lock_.AssertAcquired(); |
+ return first_offset_; |
+ } |
+ Result result() const { |
+ lock_.AssertAcquired(); |
+ return result_; |
+ } |
+ void set_result(Result r) { |
+ lock_.AssertAcquired(); |
+ result_ = r; |
+ } |
void AcquireReaderLock(Client* client) { |
+ lock_.AssertAcquired(); |
DCHECK(!notification_task_runner_); |
DCHECK(!client_); |
notification_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
@@ -99,11 +120,13 @@ class SharedMemoryDataConsumerHandle::Context final |
} |
} |
void ReleaseReaderLock() { |
+ lock_.AssertAcquired(); |
DCHECK(notification_task_runner_); |
notification_task_runner_ = nullptr; |
client_ = nullptr; |
} |
void PostNotify() { |
+ lock_.AssertAcquired(); |
auto runner = notification_task_runner_; |
if (!runner) |
return; |
@@ -113,10 +136,12 @@ class SharedMemoryDataConsumerHandle::Context final |
runner->PostTask(FROM_HERE, |
base::Bind(&Context::NotifyInternal, this, false)); |
} |
+ // Must be called with |lock_| not aquired. |
void Notify() { NotifyInternal(true); } |
// This function doesn't work in the destructor if |on_reader_detached_| is |
// not null. |
void ResetOnReaderDetached() { |
+ lock_.AssertAcquired(); |
if (on_reader_detached_.is_null()) { |
DCHECK(!is_on_reader_detached_valid_); |
return; |
@@ -132,14 +157,25 @@ class SharedMemoryDataConsumerHandle::Context final |
FROM_HERE, base::Bind(&Context::ResetOnReaderDetachedWithLock, this)); |
} |
} |
- bool is_handle_locked() const { return notification_task_runner_; } |
+ bool is_handle_locked() const { |
+ lock_.AssertAcquired(); |
+ return notification_task_runner_; |
+ } |
bool IsReaderBoundToCurrentThread() const { |
+ lock_.AssertAcquired(); |
return notification_task_runner_ && |
notification_task_runner_->BelongsToCurrentThread(); |
} |
- bool is_handle_active() const { return is_handle_active_; } |
- void set_is_handle_active(bool b) { is_handle_active_ = b; } |
+ bool is_handle_active() const { |
+ lock_.AssertAcquired(); |
+ return is_handle_active_; |
+ } |
+ void set_is_handle_active(bool b) { |
+ lock_.AssertAcquired(); |
+ is_handle_active_ = b; |
+ } |
void Consume(size_t s) { |
+ lock_.AssertAcquired(); |
first_offset_ += s; |
auto top = Top(); |
if (static_cast<size_t>(top->length()) <= first_offset_) { |
@@ -149,18 +185,24 @@ class SharedMemoryDataConsumerHandle::Context final |
} |
} |
bool is_two_phase_read_in_progress() const { |
+ lock_.AssertAcquired(); |
return is_two_phase_read_in_progress_; |
} |
void set_is_two_phase_read_in_progress(bool b) { |
+ lock_.AssertAcquired(); |
is_two_phase_read_in_progress_ = b; |
} |
+ // Can be called with |lock_| not aquired. |
base::Lock& lock() { return lock_; } |
private: |
+ // Must be called with |lock_| not aquired. |
void NotifyInternal(bool repost) { |
- // Note that this function is not protected by |lock_|. |
- |
- auto runner = notification_task_runner_; |
+ scoped_refptr<base::SingleThreadTaskRunner> runner; |
+ { |
+ base::AutoLock lock(lock_); |
+ runner = notification_task_runner_; |
+ } |
if (!runner) |
return; |
@@ -180,6 +222,7 @@ class SharedMemoryDataConsumerHandle::Context final |
} |
} |
void Clear() { |
+ lock_.AssertAcquired(); |
for (auto& data : queue_) { |
delete data; |
} |
@@ -190,6 +233,7 @@ class SharedMemoryDataConsumerHandle::Context final |
// null. We have an assert in the destructor. |
ResetOnReaderDetached(); |
} |
+ // Must be called with |lock_| not aquired. |
void ResetOnReaderDetachedWithLock() { |
base::AutoLock lock(lock_); |
ResetOnReaderDetached(); |
@@ -197,6 +241,7 @@ class SharedMemoryDataConsumerHandle::Context final |
friend class base::RefCountedThreadSafe<Context>; |
~Context() { |
+ base::AutoLock lock(lock_); |
DCHECK(on_reader_detached_.is_null()); |
// This is necessary because the queue stores raw pointers. |
@@ -273,44 +318,33 @@ void SharedMemoryDataConsumerHandle::Writer::AddData( |
} |
void SharedMemoryDataConsumerHandle::Writer::Close() { |
- bool needs_notification = false; |
- |
- { |
- base::AutoLock lock(context_->lock()); |
- if (context_->result() == Ok) { |
- context_->set_result(Done); |
- context_->ResetOnReaderDetached(); |
- needs_notification = context_->IsEmpty(); |
+ base::AutoLock lock(context_->lock()); |
+ if (context_->result() == Ok) { |
+ context_->set_result(Done); |
+ context_->ResetOnReaderDetached(); |
+ if (context_->IsEmpty()) { |
+ // We cannot issue the notification synchronously because this function |
+ // can be called in the client's callback. |
+ context_->PostNotify(); |
} |
} |
- if (needs_notification) { |
- // We cannot issue the notification synchronously because this function can |
- // be called in the client's callback. |
- context_->PostNotify(); |
- } |
} |
void SharedMemoryDataConsumerHandle::Writer::Fail() { |
- bool needs_notification = false; |
- { |
- base::AutoLock lock(context_->lock()); |
- if (context_->result() == Ok) { |
- // TODO(yhirano): Use an appropriate error code other than |
- // UnexpectedError. |
- context_->set_result(UnexpectedError); |
- |
- if (context_->is_two_phase_read_in_progress()) { |
- // If we are in two-phase read session, we cannot discard the data. We |
- // will clear the queue at the end of the session. |
- } else { |
- context_->ClearQueue(); |
- } |
+ base::AutoLock lock(context_->lock()); |
+ if (context_->result() == Ok) { |
+ // TODO(yhirano): Use an appropriate error code other than |
+ // UnexpectedError. |
+ context_->set_result(UnexpectedError); |
- context_->ResetOnReaderDetached(); |
- needs_notification = true; |
+ if (context_->is_two_phase_read_in_progress()) { |
+ // If we are in two-phase read session, we cannot discard the data. We |
+ // will clear the queue at the end of the session. |
+ } else { |
+ context_->ClearQueue(); |
} |
- } |
- if (needs_notification) { |
+ |
+ context_->ResetOnReaderDetached(); |
// We cannot issue the notification synchronously because this function can |
// be called in the client's callback. |
context_->PostNotify(); |