| Index: ppapi/shared_impl/callback_tracker.cc
|
| diff --git a/ppapi/shared_impl/callback_tracker.cc b/ppapi/shared_impl/callback_tracker.cc
|
| index feefb0e117d70aa862553838656da09763927824..e5154884a3159813b6d9bbff738dd2eab74e6fd3 100644
|
| --- a/ppapi/shared_impl/callback_tracker.cc
|
| +++ b/ppapi/shared_impl/callback_tracker.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/logging.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "ppapi/c/pp_completion_callback.h"
|
| +#include "ppapi/shared_impl/proxy_lock.h"
|
| #include "ppapi/shared_impl/tracked_callback.h"
|
|
|
| namespace ppapi {
|
| @@ -20,9 +21,17 @@ namespace ppapi {
|
| CallbackTracker::CallbackTracker() {}
|
|
|
| void CallbackTracker::AbortAll() {
|
| - // Iterate over a copy since |Abort()| calls |Remove()| (indirectly).
|
| - // TODO(viettrungluu): This obviously isn't so efficient.
|
| - CallbackSetMap pending_callbacks_copy = pending_callbacks_;
|
| + // TrackedCallback::Abort() assumes that the ProxyLock is acquired.
|
| + ProxyLock::AssertAcquired();
|
| +
|
| + // Iterate over a copy:
|
| + // 1) because |Abort()| calls |Remove()| (indirectly).
|
| + // 2) So we can drop the lock before calling in to TrackedCallback.
|
| + CallbackSetMap pending_callbacks_copy;
|
| + {
|
| + base::AutoLock acquire(lock_);
|
| + pending_callbacks_copy = pending_callbacks_;
|
| + }
|
| for (CallbackSetMap::iterator it1 = pending_callbacks_copy.begin();
|
| it1 != pending_callbacks_copy.end();
|
| ++it1) {
|
| @@ -36,15 +45,18 @@ void CallbackTracker::AbortAll() {
|
|
|
| void CallbackTracker::PostAbortForResource(PP_Resource resource_id) {
|
| CHECK(resource_id != 0);
|
| - CallbackSetMap::iterator it1 = pending_callbacks_.find(resource_id);
|
| - if (it1 == pending_callbacks_.end())
|
| - return;
|
| - for (CallbackSet::iterator it2 = it1->second.begin();
|
| - it2 != it1->second.end();
|
| - ++it2) {
|
| - // Post the abort.
|
| - (*it2)->PostAbort();
|
| + CallbackSet callbacks_for_resource;
|
| + {
|
| + base::AutoLock acquire(lock_);
|
| + CallbackSetMap::iterator iter = pending_callbacks_.find(resource_id);
|
| + if (iter == pending_callbacks_.end())
|
| + return;
|
| + // Copy the set so we can drop the lock before calling in to
|
| + // TrackedCallback.
|
| + callbacks_for_resource = iter->second;
|
| }
|
| + for (const auto& iter : callbacks_for_resource)
|
| + iter->PostAbort();
|
| }
|
|
|
| CallbackTracker::~CallbackTracker() {
|
| @@ -54,6 +66,7 @@ CallbackTracker::~CallbackTracker() {
|
|
|
| void CallbackTracker::Add(
|
| const scoped_refptr<TrackedCallback>& tracked_callback) {
|
| + base::AutoLock acquire(lock_);
|
| PP_Resource resource_id = tracked_callback->resource_id();
|
| DCHECK(pending_callbacks_[resource_id].find(tracked_callback) ==
|
| pending_callbacks_[resource_id].end());
|
| @@ -62,6 +75,7 @@ void CallbackTracker::Add(
|
|
|
| void CallbackTracker::Remove(
|
| const scoped_refptr<TrackedCallback>& tracked_callback) {
|
| + base::AutoLock acquire(lock_);
|
| CallbackSetMap::iterator map_it =
|
| pending_callbacks_.find(tracked_callback->resource_id());
|
| DCHECK(map_it != pending_callbacks_.end());
|
|
|