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

Side by Side Diff: ppapi/thunk/enter.cc

Issue 10910099: PPAPI: Make CompletionCallbacks work right on background threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 8 years, 1 month 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 | « ppapi/tests/test_utils.cc ('k') | ppapi/thunk/ppb_message_loop_api.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/thunk/enter.h" 5 #include "ppapi/thunk/enter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 retval_ = callback_->BlockUntilComplete(); 80 retval_ = callback_->BlockUntilComplete();
81 } else { 81 } else {
82 // The callback is not blocking and the operation will complete 82 // The callback is not blocking and the operation will complete
83 // asynchronously, so there's nothing to do. 83 // asynchronously, so there's nothing to do.
84 retval_ = result; 84 retval_ = result;
85 } 85 }
86 } else { 86 } else {
87 // The function completed synchronously. 87 // The function completed synchronously.
88 if (callback_->is_required()) { 88 if (callback_->is_required()) {
89 // This is a required callback, so we must issue it asynchronously. 89 // This is a required callback, so we must issue it asynchronously.
90 // TODO(dmichael) make this work so that a call from a background thread
91 // goes back to that thread.
92 callback_->PostRun(result); 90 callback_->PostRun(result);
93 retval_ = PP_OK_COMPLETIONPENDING; 91 retval_ = PP_OK_COMPLETIONPENDING;
94 } else { 92 } else {
95 // The callback is blocking or optional, so all we need to do is mark 93 // The callback is blocking or optional, so all we need to do is mark
96 // the callback as completed so that it won't be issued later. 94 // the callback as completed so that it won't be issued later.
97 callback_->MarkAsCompleted(); 95 callback_->MarkAsCompleted();
98 retval_ = result; 96 retval_ = result;
99 } 97 }
100 } 98 }
101 callback_ = NULL; 99 callback_ = NULL;
102 return retval_; 100 return retval_;
103 } 101 }
104 102
105 // static 103 // static
106 Resource* EnterBase::GetResource(PP_Resource resource) { 104 Resource* EnterBase::GetResource(PP_Resource resource) {
107 return PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource); 105 return PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource);
108 } 106 }
109 107
110 void EnterBase::SetStateForCallbackError(bool report_error) { 108 void EnterBase::SetStateForCallbackError(bool report_error) {
111 if (!CallbackIsValid()) { 109 if (PpapiGlobals::Get()->IsHostGlobals()) {
112 callback_->MarkAsCompleted(); 110 // In-process plugins can't make PPAPI calls off the main thread.
113 callback_ = NULL; 111 CHECK(IsMainThread());
114 retval_ = PP_ERROR_BLOCKS_MAIN_THREAD; 112 }
115 if (report_error) { 113 if (callback_) {
116 std::string message( 114 if (callback_->is_blocking() && IsMainThread()) {
117 "Blocking callbacks are not allowed on the main thread."); 115 // Blocking callbacks are never allowed on the main thread.
118 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, 116 callback_->MarkAsCompleted();
119 std::string(), message); 117 callback_ = NULL;
118 retval_ = PP_ERROR_BLOCKS_MAIN_THREAD;
119 if (report_error) {
120 std::string message(
121 "Blocking callbacks are not allowed on the main thread.");
122 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR,
123 std::string(), message);
124 }
125 } else if (!IsMainThread() &&
126 callback_->has_null_target_loop() &&
127 !callback_->is_blocking()) {
128 // On a non-main thread, there must be a valid target loop for non-
129 // blocking callbacks, or we will have no place to run them.
130
131 // If the callback is required, there's no nice way to tell the plugin.
132 // We can't run their callback asynchronously without a message loop, and
133 // the plugin won't expect any return code other than
134 // PP_OK_COMPLETIONPENDING. So we crash to make the problem more obvious.
135 if (callback_->is_required()) {
136 std::string message("Attempted to use a required callback, but there"
137 "is no attached message loop on which to run the"
138 "callback.");
139 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR,
140 std::string(), message);
141 LOG(FATAL) << message;
142 }
143
144 callback_->MarkAsCompleted();
145 callback_ = NULL;
146 retval_ = PP_ERROR_NO_MESSAGE_LOOP;
147 if (report_error) {
148 std::string message(
149 "The calling thread must have a message loop attached.");
150 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR,
151 std::string(), message);
152 }
120 } 153 }
121 } 154 }
122 } 155 }
123 156
124 bool EnterBase::CallbackIsValid() const {
125 // A callback is only considered invalid if it is blocking and we're on the
126 // main thread.
127 return !callback_ || !callback_->is_blocking() || !IsMainThread();
128 }
129
130 void EnterBase::ClearCallback() { 157 void EnterBase::ClearCallback() {
131 callback_ = NULL; 158 callback_ = NULL;
132 } 159 }
133 160
134 void EnterBase::SetStateForResourceError(PP_Resource pp_resource, 161 void EnterBase::SetStateForResourceError(PP_Resource pp_resource,
135 Resource* resource_base, 162 Resource* resource_base,
136 void* object, 163 void* object,
137 bool report_error) { 164 bool report_error) {
138 // Check for callback errors. If we get any, SetStateForCallbackError will 165 // Check for callback errors. If we get any, SetStateForCallbackError will
139 // emit a log message. But we also want to check for resource errors. If there 166 // emit a log message. But we also want to check for resource errors. If there
140 // are both kinds of errors, we'll emit two log messages and return 167 // are both kinds of errors, we'll emit two log messages and return
141 // PP_ERROR_BADRESOURCE. 168 // PP_ERROR_BADRESOURCE.
142 SetStateForCallbackError(report_error); 169 SetStateForCallbackError(report_error);
143 170
144 if (object) 171 if (object)
145 return; // Everything worked. 172 return; // Everything worked.
146 173
147 if (callback_ && callback_->is_required()) { 174 if (callback_ && callback_->is_required()) {
148 // TODO(dmichael) make this work so that a call from a background thread
149 // goes back to that thread.
150 callback_->PostRun(static_cast<int32_t>(PP_ERROR_BADRESOURCE)); 175 callback_->PostRun(static_cast<int32_t>(PP_ERROR_BADRESOURCE));
151 callback_ = NULL; 176 callback_ = NULL;
152 retval_ = PP_OK_COMPLETIONPENDING; 177 retval_ = PP_OK_COMPLETIONPENDING;
153 } else { 178 } else {
154 if (callback_) 179 if (callback_)
155 callback_->MarkAsCompleted(); 180 callback_->MarkAsCompleted();
156 callback_ = NULL; 181 callback_ = NULL;
157 retval_ = PP_ERROR_BADRESOURCE; 182 retval_ = PP_ERROR_BADRESOURCE;
158 } 183 }
159 184
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 : EnterBase(), 290 : EnterBase(),
266 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { 291 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) {
267 SetStateForFunctionError(instance, functions_, true); 292 SetStateForFunctionError(instance, functions_, true);
268 } 293 }
269 294
270 EnterResourceCreationNoLock::~EnterResourceCreationNoLock() { 295 EnterResourceCreationNoLock::~EnterResourceCreationNoLock() {
271 } 296 }
272 297
273 } // namespace thunk 298 } // namespace thunk
274 } // namespace ppapi 299 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/tests/test_utils.cc ('k') | ppapi/thunk/ppb_message_loop_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698