Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(537)

Side by Side Diff: webkit/plugins/ppapi/callbacks.cc

Issue 9015009: Use the new callback tracker and delete the old one (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add IsPending Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/plugins/ppapi/callbacks.h ('k') | webkit/plugins/ppapi/callbacks_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "webkit/plugins/ppapi/callbacks.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "base/message_loop.h"
13 #include "ppapi/c/pp_completion_callback.h"
14 #include "ppapi/c/pp_errors.h"
15
16 namespace webkit {
17 namespace ppapi {
18
19 // CallbackTracker -------------------------------------------------------------
20
21 CallbackTracker::CallbackTracker() {
22 }
23
24 void CallbackTracker::AbortAll() {
25 // Iterate over a copy since |Abort()| calls |Remove()| (indirectly).
26 // TODO(viettrungluu): This obviously isn't so efficient.
27 CallbackSetMap pending_callbacks_copy = pending_callbacks_;
28 for (CallbackSetMap::iterator it1 = pending_callbacks_copy.begin();
29 it1 != pending_callbacks_copy.end(); ++it1) {
30 for (CallbackSet::iterator it2 = it1->second.begin();
31 it2 != it1->second.end(); ++it2) {
32 (*it2)->Abort();
33 }
34 }
35 }
36
37 void CallbackTracker::PostAbortForResource(PP_Resource resource_id) {
38 CHECK(resource_id != 0);
39 CallbackSetMap::iterator it1 = pending_callbacks_.find(resource_id);
40 if (it1 == pending_callbacks_.end())
41 return;
42 for (CallbackSet::iterator it2 = it1->second.begin();
43 it2 != it1->second.end(); ++it2) {
44 // Post the abort.
45 (*it2)->PostAbort();
46 }
47 }
48
49 CallbackTracker::~CallbackTracker() {
50 // All callbacks must be aborted before destruction.
51 CHECK_EQ(0u, pending_callbacks_.size());
52 }
53
54 void CallbackTracker::Add(
55 const scoped_refptr<TrackedCallback>& tracked_callback) {
56 PP_Resource resource_id = tracked_callback->resource_id();
57 DCHECK(pending_callbacks_[resource_id].find(tracked_callback) ==
58 pending_callbacks_[resource_id].end());
59 pending_callbacks_[resource_id].insert(tracked_callback);
60 }
61
62 void CallbackTracker::Remove(
63 const scoped_refptr<TrackedCallback>& tracked_callback) {
64 CallbackSetMap::iterator map_it =
65 pending_callbacks_.find(tracked_callback->resource_id());
66 DCHECK(map_it != pending_callbacks_.end());
67 CallbackSet::iterator it = map_it->second.find(tracked_callback);
68 DCHECK(it != map_it->second.end());
69 map_it->second.erase(it);
70
71 // If there are no pending callbacks left for this ID, get rid of the entry.
72 if (map_it->second.empty())
73 pending_callbacks_.erase(map_it);
74 }
75
76 // TrackedCallback -------------------------------------------------------------
77
78 TrackedCallback::TrackedCallback(const scoped_refptr<CallbackTracker>& tracker,
79 PP_Resource resource_id)
80 : ALLOW_THIS_IN_INITIALIZER_LIST(abort_impl_factory_(this)),
81 tracker_(tracker),
82 resource_id_(resource_id),
83 completed_(false),
84 aborted_(false) {
85 tracker_->Add(make_scoped_refptr(this));
86 }
87
88 void TrackedCallback::Abort() {
89 if (!completed()) {
90 aborted_ = true;
91 AbortImpl();
92 }
93 }
94
95 void TrackedCallback::PostAbort() {
96 if (!completed()) {
97 aborted_ = true;
98 // Post a task for the abort (only if necessary).
99 if (!abort_impl_factory_.HasWeakPtrs()) {
100 MessageLoop::current()->PostTask(
101 FROM_HERE,
102 base::Bind(&TrackedCallback::AbortImpl,
103 abort_impl_factory_.GetWeakPtr()));
104 }
105 }
106 }
107
108 TrackedCallback::~TrackedCallback() {
109 // The tracker must ensure that the callback is completed (maybe abortively).
110 DCHECK(completed_);
111 }
112
113 void TrackedCallback::MarkAsCompleted() {
114 DCHECK(!completed());
115
116 // We will be removed; maintain a reference to ensure we won't be deleted
117 // until we're done.
118 scoped_refptr<TrackedCallback> thiz = this;
119 completed_ = true;
120 tracker_->Remove(thiz);
121 tracker_ = NULL;
122 }
123
124 // TrackedCompletionCallback ---------------------------------------------------
125
126 TrackedCompletionCallback::TrackedCompletionCallback(
127 const scoped_refptr<CallbackTracker>& tracker,
128 PP_Resource resource_id,
129 const PP_CompletionCallback& callback)
130 : TrackedCallback(tracker, resource_id),
131 callback_(callback) {
132 }
133
134 void TrackedCompletionCallback::Run(int32_t result) {
135 if (!completed()) {
136 // Cancel any pending calls.
137 abort_impl_factory_.InvalidateWeakPtrs();
138
139 // Copy |callback_| and look at |aborted()| now, since |MarkAsCompleted()|
140 // may delete us.
141 PP_CompletionCallback callback = callback_;
142 if (aborted())
143 result = PP_ERROR_ABORTED;
144
145 // Do this before running the callback in case of reentrancy (which
146 // shouldn't happen, but avoid strange failures).
147 MarkAsCompleted();
148 PP_RunCompletionCallback(&callback, result);
149 }
150 }
151
152 void TrackedCompletionCallback::AbortImpl() {
153 Run(PP_ERROR_ABORTED);
154 }
155
156 } // namespace ppapi
157 } // namespace webkit
OLDNEW
« no previous file with comments | « webkit/plugins/ppapi/callbacks.h ('k') | webkit/plugins/ppapi/callbacks_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698