| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/shared_impl/tracked_callback.h" | 5 #include "ppapi/shared_impl/tracked_callback.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
| 12 #include "ppapi/c/pp_completion_callback.h" | 12 #include "ppapi/c/pp_completion_callback.h" |
| 13 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/c/pp_errors.h" |
| 14 #include "ppapi/c/ppb_message_loop.h" | 14 #include "ppapi/c/ppb_message_loop.h" |
| 15 #include "ppapi/shared_impl/callback_tracker.h" | 15 #include "ppapi/shared_impl/callback_tracker.h" |
| 16 #include "ppapi/shared_impl/ppapi_globals.h" | 16 #include "ppapi/shared_impl/ppapi_globals.h" |
| 17 #include "ppapi/shared_impl/ppb_message_loop_shared.h" | 17 #include "ppapi/shared_impl/ppb_message_loop_shared.h" |
| 18 #include "ppapi/shared_impl/proxy_lock.h" | 18 #include "ppapi/shared_impl/proxy_lock.h" |
| 19 #include "ppapi/shared_impl/resource.h" | 19 #include "ppapi/shared_impl/resource.h" |
| 20 | 20 |
| 21 namespace ppapi { | 21 namespace ppapi { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 bool IsMainThread() { | 25 bool IsMainThread() { |
| 26 return | 26 return |
| 27 PpapiGlobals::Get()->GetMainThreadMessageLoop()->BelongsToCurrentThread(); | 27 PpapiGlobals::Get()->GetMainThreadMessageLoop()->BelongsToCurrentThread(); |
| 28 } | 28 } |
| 29 | 29 |
| 30 int32_t RunCompletionTask(TrackedCallback::CompletionTask completion_task, |
| 31 int32_t result) { |
| 32 int32_t task_result = completion_task.Run(result); |
| 33 if (result != PP_ERROR_ABORTED) |
| 34 result = task_result; |
| 35 return result; |
| 36 } |
| 37 |
| 30 } // namespace | 38 } // namespace |
| 31 | 39 |
| 32 // TrackedCallback ------------------------------------------------------------- | 40 // TrackedCallback ------------------------------------------------------------- |
| 33 | 41 |
| 34 // Note: don't keep a Resource* since it may go out of scope before us. | 42 // Note: don't keep a Resource* since it may go out of scope before us. |
| 35 TrackedCallback::TrackedCallback( | 43 TrackedCallback::TrackedCallback( |
| 36 Resource* resource, | 44 Resource* resource, |
| 37 const PP_CompletionCallback& callback) | 45 const PP_CompletionCallback& callback) |
| 38 : is_scheduled_(false), | 46 : is_scheduled_(false), |
| 39 resource_id_(resource ? resource->pp_resource() : 0), | 47 resource_id_(resource ? resource->pp_resource() : 0), |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 // Wait()s. | 129 // Wait()s. |
| 122 operation_completed_condvar_->Signal(); | 130 operation_completed_condvar_->Signal(); |
| 123 } else { | 131 } else { |
| 124 // If there's a target_loop_, and we're not on the right thread, we need to | 132 // If there's a target_loop_, and we're not on the right thread, we need to |
| 125 // post to target_loop_. | 133 // post to target_loop_. |
| 126 if (target_loop_.get() && | 134 if (target_loop_.get() && |
| 127 target_loop_.get() != PpapiGlobals::Get()->GetCurrentMessageLoop()) { | 135 target_loop_.get() != PpapiGlobals::Get()->GetCurrentMessageLoop()) { |
| 128 PostRun(result); | 136 PostRun(result); |
| 129 return; | 137 return; |
| 130 } | 138 } |
| 131 // Copy |callback_| now, since |MarkAsCompleted()| may delete us. | 139 |
| 140 // Copy callback fields now, since |MarkAsCompleted()| may delete us. |
| 132 PP_CompletionCallback callback = callback_; | 141 PP_CompletionCallback callback = callback_; |
| 133 // Do this before running the callback in case of reentrancy (which | 142 CompletionTask completion_task = completion_task_; |
| 134 // shouldn't happen, but avoid strange failures). | 143 completion_task_.Reset(); |
| 144 // Do this before running the callback in case of reentrancy from running |
| 145 // the completion task. |
| 135 MarkAsCompleted(); | 146 MarkAsCompleted(); |
| 147 |
| 148 if (!completion_task.is_null()) |
| 149 result = RunCompletionTask(completion_task, result); |
| 150 |
| 136 // TODO(dmichael): Associate a message loop with the callback; if it's not | 151 // TODO(dmichael): Associate a message loop with the callback; if it's not |
| 137 // the same as the current thread's loop, then post it to the right loop. | 152 // the same as the current thread's loop, then post it to the right loop. |
| 138 CallWhileUnlocked(PP_RunCompletionCallback, &callback, result); | 153 CallWhileUnlocked(PP_RunCompletionCallback, &callback, result); |
| 139 } | 154 } |
| 140 } | 155 } |
| 141 | 156 |
| 142 void TrackedCallback::PostRun(int32_t result) { | 157 void TrackedCallback::PostRun(int32_t result) { |
| 143 if (completed()) { | 158 if (completed()) { |
| 144 NOTREACHED(); | 159 NOTREACHED(); |
| 145 return; | 160 return; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 157 // classes protect against having a null target_loop_ otherwise). | 172 // classes protect against having a null target_loop_ otherwise). |
| 158 DCHECK(IsMainThread()); | 173 DCHECK(IsMainThread()); |
| 159 DCHECK(PpapiGlobals::Get()->IsHostGlobals()); | 174 DCHECK(PpapiGlobals::Get()->IsHostGlobals()); |
| 160 base::MessageLoop::current()->PostTask(FROM_HERE, callback_closure); | 175 base::MessageLoop::current()->PostTask(FROM_HERE, callback_closure); |
| 161 } else { | 176 } else { |
| 162 target_loop_->PostClosure(FROM_HERE, callback_closure, 0); | 177 target_loop_->PostClosure(FROM_HERE, callback_closure, 0); |
| 163 } | 178 } |
| 164 is_scheduled_ = true; | 179 is_scheduled_ = true; |
| 165 } | 180 } |
| 166 | 181 |
| 182 void TrackedCallback::set_completion_task( |
| 183 const CompletionTask& completion_task) { |
| 184 DCHECK(completion_task_.is_null()); |
| 185 completion_task_ = completion_task; |
| 186 } |
| 187 |
| 167 // static | 188 // static |
| 168 bool TrackedCallback::IsPending( | 189 bool TrackedCallback::IsPending( |
| 169 const scoped_refptr<TrackedCallback>& callback) { | 190 const scoped_refptr<TrackedCallback>& callback) { |
| 170 if (!callback.get()) | 191 if (!callback.get()) |
| 171 return false; | 192 return false; |
| 172 if (callback->aborted()) | 193 if (callback->aborted()) |
| 173 return false; | 194 return false; |
| 174 return !callback->completed(); | 195 return !callback->completed(); |
| 175 } | 196 } |
| 176 | 197 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 188 // BlockUntilComplete should never be called for in-process plugins, where | 209 // BlockUntilComplete should never be called for in-process plugins, where |
| 189 // blocking callbacks are not supported. | 210 // blocking callbacks are not supported. |
| 190 CHECK(operation_completed_condvar_.get()); | 211 CHECK(operation_completed_condvar_.get()); |
| 191 if (!is_blocking() || !operation_completed_condvar_.get()) { | 212 if (!is_blocking() || !operation_completed_condvar_.get()) { |
| 192 NOTREACHED(); | 213 NOTREACHED(); |
| 193 return PP_ERROR_FAILED; | 214 return PP_ERROR_FAILED; |
| 194 } | 215 } |
| 195 | 216 |
| 196 while (!completed()) | 217 while (!completed()) |
| 197 operation_completed_condvar_->Wait(); | 218 operation_completed_condvar_->Wait(); |
| 219 |
| 220 if (!completion_task_.is_null()) { |
| 221 result_for_blocked_callback_ = |
| 222 RunCompletionTask(completion_task_, result_for_blocked_callback_); |
| 223 completion_task_.Reset(); |
| 224 } |
| 198 return result_for_blocked_callback_; | 225 return result_for_blocked_callback_; |
| 199 } | 226 } |
| 200 | 227 |
| 201 void TrackedCallback::MarkAsCompleted() { | 228 void TrackedCallback::MarkAsCompleted() { |
| 202 DCHECK(!completed()); | 229 DCHECK(!completed()); |
| 203 | 230 |
| 204 // We will be removed; maintain a reference to ensure we won't be deleted | 231 // We will be removed; maintain a reference to ensure we won't be deleted |
| 205 // until we're done. | 232 // until we're done. |
| 206 scoped_refptr<TrackedCallback> thiz = this; | 233 scoped_refptr<TrackedCallback> thiz = this; |
| 207 completed_ = true; | 234 completed_ = true; |
| 208 // We may not have a valid resource, in which case we're not in the tracker. | 235 // We may not have a valid resource, in which case we're not in the tracker. |
| 209 if (resource_id_) | 236 if (resource_id_) |
| 210 tracker_->Remove(thiz); | 237 tracker_->Remove(thiz); |
| 211 tracker_ = NULL; | 238 tracker_ = NULL; |
| 212 } | 239 } |
| 213 | 240 |
| 214 } // namespace ppapi | 241 } // namespace ppapi |
| OLD | NEW |