1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/shared_impl/callback_tracker.h"
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "ppapi/c/pp_completion_callback.h"
14 #include "ppapi/shared_impl/proxy_lock.h"
15 #include "ppapi/shared_impl/tracked_callback.h"
19 // CallbackTracker -------------------------------------------------------------
21 CallbackTracker::CallbackTracker() : abort_all_called_(false) {}
23 void CallbackTracker::AbortAll() {
24 // Iterate over a copy:
25 // 1) because |Abort()| calls |Remove()| (indirectly).
26 // 2) So we can drop the lock before calling in to TrackedCallback.
27 CallbackSetMap pending_callbacks_copy
;
29 base::AutoLock
acquire(lock_
);
30 pending_callbacks_copy
= pending_callbacks_
;
31 abort_all_called_
= true;
33 for (CallbackSetMap::iterator it1
= pending_callbacks_copy
.begin();
34 it1
!= pending_callbacks_copy
.end();
36 for (CallbackSet::iterator it2
= it1
->second
.begin();
37 it2
!= it1
->second
.end();
44 void CallbackTracker::PostAbortForResource(PP_Resource resource_id
) {
45 // Only TrackedCallbacks with a valid resource should appear in the tracker.
46 DCHECK_NE(resource_id
, 0);
47 CallbackSet callbacks_for_resource
;
49 base::AutoLock
acquire(lock_
);
50 CallbackSetMap::iterator iter
= pending_callbacks_
.find(resource_id
);
51 // The resource may have no callbacks, so it won't be found, and we're done.
52 if (iter
== pending_callbacks_
.end())
54 // Copy the set so we can drop the lock before calling in to
56 callbacks_for_resource
= iter
->second
;
58 for (const auto& iter
: callbacks_for_resource
) {
63 CallbackTracker::~CallbackTracker() {
64 // All callbacks must be aborted before destruction.
65 CHECK_EQ(0u, pending_callbacks_
.size());
68 void CallbackTracker::Add(
69 const scoped_refptr
<TrackedCallback
>& tracked_callback
) {
70 base::AutoLock
acquire(lock_
);
71 DCHECK(!abort_all_called_
);
72 PP_Resource resource_id
= tracked_callback
->resource_id();
73 // Only TrackedCallbacks with a valid resource should appear in the tracker.
74 DCHECK_NE(resource_id
, 0);
75 DCHECK(pending_callbacks_
[resource_id
].find(tracked_callback
) ==
76 pending_callbacks_
[resource_id
].end());
77 pending_callbacks_
[resource_id
].insert(tracked_callback
);
80 void CallbackTracker::Remove(
81 const scoped_refptr
<TrackedCallback
>& tracked_callback
) {
82 base::AutoLock
acquire(lock_
);
83 CallbackSetMap::iterator map_it
=
84 pending_callbacks_
.find(tracked_callback
->resource_id());
85 DCHECK(map_it
!= pending_callbacks_
.end());
86 CallbackSet::iterator it
= map_it
->second
.find(tracked_callback
);
87 DCHECK(it
!= map_it
->second
.end());
88 map_it
->second
.erase(it
);
90 // If there are no pending callbacks left for this ID, get rid of the entry.
91 if (map_it
->second
.empty())
92 pending_callbacks_
.erase(map_it
);