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

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

Issue 10081020: PPAPI: Make blocking completion callbacks work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updated TestURLLoader to test blocking callbacks. Created 8 years, 8 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
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 #ifndef PPAPI_THUNK_ENTER_H_ 5 #ifndef PPAPI_THUNK_ENTER_H_
6 #define PPAPI_THUNK_ENTER_H_ 6 #define PPAPI_THUNK_ENTER_H_
7 7
8 #include <string>
9
8 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/synchronization/lock.h"
13 #include "ppapi/c/pp_errors.h"
9 #include "ppapi/c/pp_resource.h" 14 #include "ppapi/c/pp_resource.h"
10 #include "ppapi/shared_impl/api_id.h" 15 #include "ppapi/shared_impl/api_id.h"
11 #include "ppapi/shared_impl/function_group_base.h" 16 #include "ppapi/shared_impl/function_group_base.h"
12 #include "ppapi/shared_impl/ppapi_globals.h" 17 #include "ppapi/shared_impl/ppapi_globals.h"
13 #include "ppapi/shared_impl/proxy_lock.h" 18 #include "ppapi/shared_impl/proxy_lock.h"
14 #include "ppapi/shared_impl/resource.h" 19 #include "ppapi/shared_impl/resource.h"
15 #include "ppapi/shared_impl/resource_tracker.h" 20 #include "ppapi/shared_impl/resource_tracker.h"
16 #include "ppapi/thunk/ppapi_thunk_export.h" 21 #include "ppapi/thunk/ppapi_thunk_export.h"
17 #include "ppapi/thunk/ppb_instance_api.h" 22 #include "ppapi/thunk/ppb_instance_api.h"
18 #include "ppapi/thunk/resource_creation_api.h" 23 #include "ppapi/thunk/resource_creation_api.h"
19 24
20 namespace ppapi { 25 namespace ppapi {
26 class TrackedCallback;
27
21 namespace thunk { 28 namespace thunk {
22 29
23 // Enter* helper objects: These objects wrap a call from the C PPAPI into 30 // Enter* helper objects: These objects wrap a call from the C PPAPI into
24 // the internal implementation. They make sure the lock is acquired and will 31 // the internal implementation. They make sure the lock is acquired and will
25 // automatically set up some stuff for you. 32 // automatically set up some stuff for you.
26 // 33 //
27 // You should always check whether the enter succeeded before using the object. 34 // You should always check whether the enter succeeded before using the object.
28 // If this fails, then the instance or resource ID supplied was invalid. 35 // If this fails, then the instance or resource ID supplied was invalid.
29 // 36 //
30 // The |report_error| arguments to the constructor should indicate if errors 37 // The |report_error| arguments to the constructor should indicate if errors
(...skipping 15 matching lines...) Expand all
46 // This helps us define our RAII Enter classes easily. To make an RAII class 53 // This helps us define our RAII Enter classes easily. To make an RAII class
47 // which locks the proxy lock on construction and unlocks on destruction, 54 // which locks the proxy lock on construction and unlocks on destruction,
48 // inherit from |LockOnEntry<true>|. For cases where you don't want to lock, 55 // inherit from |LockOnEntry<true>|. For cases where you don't want to lock,
49 // inherit from |LockOnEntry<false>|. This allows us to share more code between 56 // inherit from |LockOnEntry<false>|. This allows us to share more code between
50 // Enter* and Enter*NoLock classes. 57 // Enter* and Enter*NoLock classes.
51 template <bool lock_on_entry> 58 template <bool lock_on_entry>
52 struct LockOnEntry; 59 struct LockOnEntry;
53 60
54 template <> 61 template <>
55 struct LockOnEntry<false> { 62 struct LockOnEntry<false> {
56 // TODO(dmichael) assert the lock is held. 63 #if (!NDEBUG)
64 LockOnEntry() {
65 // You must already hold the lock to use Enter*NoLock.
66 AssertLockHeld();
67 }
68 ~LockOnEntry() {
69 // You must not release the lock before leaving the scope of the
70 // Enter*NoLock.
71 AssertLockHeld();
72 }
73 private:
74 static void AssertLockHeld() {
75 base::Lock* proxy_lock = PpapiGlobals::Get()->GetProxyLock();
76 if (proxy_lock)
77 proxy_lock->AssertAcquired();
78 }
79 #endif
57 }; 80 };
58 81
59 template <> 82 template <>
60 struct LockOnEntry<true> { 83 struct LockOnEntry<true> {
61 LockOnEntry() { 84 LockOnEntry() {
62 ppapi::ProxyLock::Acquire(); 85 ppapi::ProxyLock::Acquire();
63 } 86 }
64 ~LockOnEntry() { 87 ~LockOnEntry() {
65 ppapi::ProxyLock::Release(); 88 ppapi::ProxyLock::Release();
66 } 89 }
67 }; 90 };
68 91
69 // Keep non-templatized since we need non-inline functions here. 92 // Keep non-templatized since we need non-inline functions here.
70 class PPAPI_THUNK_EXPORT EnterBase { 93 class PPAPI_THUNK_EXPORT EnterBase {
71 public: 94 public:
72 EnterBase(); 95 EnterBase();
73 explicit EnterBase(const PP_CompletionCallback& callback); 96 explicit EnterBase(PP_Resource resource);
97 EnterBase(PP_Resource resource, const PP_CompletionCallback& callback);
74 virtual ~EnterBase(); 98 virtual ~EnterBase();
75 99
76 // Sets the result. 100 // Sets the result for calls that use a completion callback. It handles making
101 // sure that "Required" callbacks are scheduled to run asynchronously and
102 // "Blocking" callbacks cause the caller to block. (Interface implementations,
103 // therefore, should not do any special casing based on the type of the
104 // callback.)
77 // 105 //
78 // Returns the "retval()". This is to support the typical usage of 106 // Returns the "retval()". This is to support the typical usage of
79 // return enter.SetResult(...); 107 // return enter.SetResult(...);
80 // without having to write a separate "return enter.retval();" line. 108 // without having to write a separate "return enter.retval();" line.
81 int32_t SetResult(int32_t result); 109 int32_t SetResult(int32_t result);
82 110
83 // Use this value as the return value for the function. 111 // Use this value as the return value for the function.
84 int32_t retval() const { return retval_; } 112 int32_t retval() const { return retval_; }
85 113
114 bool succeeded() const { return retval_ == PP_OK; }
115 bool failed() const { return !succeeded(); }
116
117 const scoped_refptr<TrackedCallback>& callback() { return callback_; }
118
86 protected: 119 protected:
87 // Helper function to return a function group from a PP_Instance. Having this 120 // Helper function to return a function group from a PP_Instance. Having this
88 // code be in the non-templatized base keeps us from having to instantiate 121 // code be in the non-templatized base keeps us from having to instantiate
89 // it in every template. 122 // it in every template.
90 FunctionGroupBase* GetFunctions(PP_Instance instance, ApiID id) const; 123 FunctionGroupBase* GetFunctions(PP_Instance instance, ApiID id) const;
91 124
92 // Helper function to return a Resource from a PP_Resource. Having this 125 // Helper function to return a Resource from a PP_Resource. Having this
93 // code be in the non-templatized base keeps us from having to instantiate 126 // code be in the non-templatized base keeps us from having to instantiate
94 // it in every template. 127 // it in every template.
95 Resource* GetResource(PP_Resource resource) const; 128 static Resource* GetResource(PP_Resource resource);
129
130 // Checks whether the callback is valid (i.e., if it is either non-blocking,
131 // or blocking and we're on a background thread). If the callback is invalid,
132 // this will set retval_ = PP_ERROR_BLOCKS_MAIN_THREAD, and if report_error is
133 // set, it will log a message to the programmer.
134 void SetStateForCallbackError(bool report_error);
135 bool CallbackIsValid() const;
96 136
97 // Does error handling associated with entering a resource. The resource_base 137 // Does error handling associated with entering a resource. The resource_base
98 // is the result of looking up the given pp_resource. The object is the 138 // is the result of looking up the given pp_resource. The object is the
99 // result of converting the base to the desired object (converted back to a 139 // result of converting the base to the desired object (converted to a void*
100 // Resource* so this function doesn't have to be templatized). The reason for 140 // so this function doesn't have to be templatized). The reason for passing
101 // passing both resource_base and object is that we can differentiate "bad 141 // both resource_base and object is that we can differentiate "bad resource
102 // resource ID" from "valid resource ID not of the currect type." 142 // ID" from "valid resource ID not of the correct type."
103 // 143 //
104 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and 144 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and
105 // if report_error is set, log a message to the programmer. 145 // if report_error is set, log a message to the programmer.
106 void SetStateForResourceError(PP_Resource pp_resource, 146 void SetStateForResourceError(PP_Resource pp_resource,
107 Resource* resource_base, 147 Resource* resource_base,
108 void* object, 148 void* object,
109 bool report_error); 149 bool report_error);
110 150
111 // Same as SetStateForResourceError except for function API. 151 // Same as SetStateForResourceError except for function API.
112 void SetStateForFunctionError(PP_Instance pp_instance, 152 void SetStateForFunctionError(PP_Instance pp_instance,
113 void* object, 153 void* object,
114 bool report_error); 154 bool report_error);
115 155
156 // For Enter objects that need a resource, we'll store a pointer to the
157 // Resource object so that we don't need to look it up more than once. For
158 // Enter objects with no resource, this will be NULL.
159 Resource* resource_;
160
116 private: 161 private:
117 // Holds the callback. The function will only be non-NULL when the 162 // Holds the callback. For Enter objects that aren't given a callback, this
118 // callback is requried. Optional callbacks don't require any special 163 // will be NULL.
119 // handling from us at this layer. 164 scoped_refptr<TrackedCallback> callback_;
120 PP_CompletionCallback callback_;
121 165
122 int32_t retval_; 166 int32_t retval_;
123 }; 167 };
124 168
125 } // namespace subtle 169 } // namespace subtle
126 170
127 // EnterFunction -------------------------------------------------------------- 171 // EnterFunction --------------------------------------------------------------
128 172
129 template<typename FunctionsT, bool lock_on_entry = true> 173 template<typename FunctionsT, bool lock_on_entry = true>
130 class EnterFunction : public subtle::EnterBase, 174 class EnterFunction : public subtle::EnterBase,
131 public subtle::LockOnEntry<lock_on_entry> { 175 public subtle::LockOnEntry<lock_on_entry> {
132 public: 176 public:
133 EnterFunction(PP_Instance instance, bool report_error) 177 EnterFunction(PP_Instance instance, bool report_error)
134 : EnterBase() { 178 : EnterBase(instance) {
135 Init(instance, report_error); 179 Init(instance, report_error);
136 } 180 }
137 EnterFunction(PP_Instance instance, 181 EnterFunction(PP_Instance instance,
138 const PP_CompletionCallback& callback, 182 const PP_CompletionCallback& callback,
139 bool report_error) 183 bool report_error)
140 : EnterBase(callback) { 184 : EnterBase(0 /* resource */, callback) {
185 // TODO(dmichael): This means that the callback_ we get is not associated
186 // even with the instance, but we need to handle that for
187 // MouseLock (maybe others?).
141 Init(instance, report_error); 188 Init(instance, report_error);
142 } 189 }
143 190
144 ~EnterFunction() {} 191 ~EnterFunction() {}
145 192
146 bool succeeded() const { return !!functions_; } 193 /* bool succeeded() const { return !!functions_ && CallbackIsValid(); }
147 bool failed() const { return !functions_; } 194 bool failed() const { return !succeeded(); }*/
148 195
149 FunctionsT* functions() { return functions_; } 196 FunctionsT* functions() { return functions_; }
150 197
151 private: 198 private:
152 void Init(PP_Instance instance, bool report_error) { 199 void Init(PP_Instance instance, bool report_error) {
153 FunctionGroupBase* base = GetFunctions(instance, FunctionsT::kApiID); 200 FunctionGroupBase* base = GetFunctions(instance, FunctionsT::kApiID);
154 if (base) 201 if (base)
155 functions_ = base->GetAs<FunctionsT>(); 202 functions_ = base->GetAs<FunctionsT>();
156 else 203 else
157 functions_ = NULL; 204 functions_ = NULL;
205 // Validate the callback.
206 SetStateForCallbackError(report_error);
207 // Validate the resource (note, if both are wrong, we will return
208 // PP_ERROR_BADARGUMENT; last in wins).
158 SetStateForFunctionError(instance, functions_, report_error); 209 SetStateForFunctionError(instance, functions_, report_error);
159 } 210 }
160 211
161 FunctionsT* functions_; 212 FunctionsT* functions_;
162 213
163 DISALLOW_COPY_AND_ASSIGN(EnterFunction); 214 DISALLOW_COPY_AND_ASSIGN(EnterFunction);
164 }; 215 };
165 216
166 // Like EnterFunction but assumes the lock is already held. 217 // Like EnterFunction but assumes the lock is already held.
167 template<typename FunctionsT> 218 template<typename FunctionsT>
168 class EnterFunctionNoLock : public EnterFunction<FunctionsT, false> { 219 class EnterFunctionNoLock : public EnterFunction<FunctionsT, false> {
169 public: 220 public:
170 EnterFunctionNoLock(PP_Instance instance, bool report_error) 221 EnterFunctionNoLock(PP_Instance instance, bool report_error)
171 : EnterFunction<FunctionsT, false>(instance, report_error) { 222 : EnterFunction<FunctionsT, false>(instance, report_error) {
172 } 223 }
173 }; 224 };
174 225
175 // Used when a caller has a resource, and wants to do EnterFunction for the 226 // Used when a caller has a resource, and wants to do EnterFunction for the
176 // instance corresponding to that resource. 227 // instance corresponding to that resource.
177 template<typename FunctionsT> 228 template<typename FunctionsT>
178 class EnterFunctionGivenResource : public EnterFunction<FunctionsT> { 229 class EnterFunctionGivenResource : public EnterFunction<FunctionsT> {
179 public: 230 public:
180 EnterFunctionGivenResource(PP_Resource resource, bool report_error) 231 EnterFunctionGivenResource(PP_Resource resource, bool report_error)
181 : EnterFunction<FunctionsT>(GetInstanceForResource(resource), 232 : EnterFunction<FunctionsT>(GetInstanceForResource(resource),
182 report_error) { 233 report_error) {
183 } 234 }
184 235
185 private: 236 private:
186 static PP_Instance GetInstanceForResource(PP_Resource resource) { 237 static PP_Instance GetInstanceForResource(PP_Resource resource) {
187 Resource* object = 238 Resource* object = subtle::EnterBase::GetResource(resource);
188 PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource);
189 return object ? object->pp_instance() : 0; 239 return object ? object->pp_instance() : 0;
190 } 240 }
191 }; 241 };
192 242
193 // EnterResource --------------------------------------------------------------- 243 // EnterResource ---------------------------------------------------------------
194 244
195 template<typename ResourceT, bool lock_on_entry = true> 245 template<typename ResourceT, bool lock_on_entry = true>
196 class EnterResource : public subtle::EnterBase, 246 class EnterResource : public subtle::EnterBase,
197 public subtle::LockOnEntry<lock_on_entry> { 247 public subtle::LockOnEntry<lock_on_entry> {
198 public: 248 public:
199 EnterResource(PP_Resource resource, bool report_error) 249 EnterResource(PP_Resource resource, bool report_error)
200 : EnterBase() { 250 : EnterBase(resource) {
201 Init(resource, report_error); 251 Init(resource, report_error);
202 } 252 }
203 EnterResource(PP_Resource resource, 253 EnterResource(PP_Resource resource, const PP_CompletionCallback& callback,
204 const PP_CompletionCallback& callback,
205 bool report_error) 254 bool report_error)
206 : EnterBase(callback) { 255 : EnterBase(resource, callback) {
207 Init(resource, report_error); 256 Init(resource, report_error);
208 } 257 }
209 ~EnterResource() {} 258 ~EnterResource() {}
210 259
211 bool succeeded() const { return !!object_; } 260 /* bool succeeded() const { return !!object_ && CallbackIsValid(); }
212 bool failed() const { return !object_; } 261 bool failed() const { return !succeeded(); }*/
213 262
214 ResourceT* object() { return object_; } 263 ResourceT* object() { return object_; }
215 Resource* resource() { return resource_; } 264 Resource* resource() { return resource_; }
216 265
217 private: 266 private:
218 void Init(PP_Resource resource, bool report_error) { 267 void Init(PP_Resource resource, bool report_error) {
219 resource_ = GetResource(resource);
220 if (resource_) 268 if (resource_)
221 object_ = resource_->GetAs<ResourceT>(); 269 object_ = resource_->GetAs<ResourceT>();
222 else 270 else
223 object_ = NULL; 271 object_ = NULL;
272 // Validate the callback.
273 SetStateForCallbackError(report_error);
274 // Validate the resource (note, if both are wrong, we will return
275 // PP_ERROR_BADRESOURCE; last in wins).
224 SetStateForResourceError(resource, resource_, object_, report_error); 276 SetStateForResourceError(resource, resource_, object_, report_error);
225 } 277 }
226 278
227 Resource* resource_;
228 ResourceT* object_; 279 ResourceT* object_;
229 280
230 DISALLOW_COPY_AND_ASSIGN(EnterResource); 281 DISALLOW_COPY_AND_ASSIGN(EnterResource);
231 }; 282 };
232 283
233 // ---------------------------------------------------------------------------- 284 // ----------------------------------------------------------------------------
234 285
235 // Like EnterResource but assumes the lock is already held. 286 // Like EnterResource but assumes the lock is already held.
236 template<typename ResourceT> 287 template<typename ResourceT>
237 class EnterResourceNoLock : public EnterResource<ResourceT, false> { 288 class EnterResourceNoLock : public EnterResource<ResourceT, false> {
238 public: 289 public:
239 EnterResourceNoLock(PP_Resource resource, bool report_error) 290 EnterResourceNoLock(PP_Resource resource, bool report_error)
240 : EnterResource<ResourceT, false>(resource, report_error) { 291 : EnterResource<ResourceT, false>(resource, report_error) {
241 } 292 }
293 EnterResourceNoLock(PP_Resource resource, PP_CompletionCallback callback,
294 bool report_error)
295 : EnterResource<ResourceT, false>(resource, callback, report_error) {
296 }
242 }; 297 };
243 298
244 // Simpler wrapper to enter the resource creation API. This is used for every 299 // Simpler wrapper to enter the resource creation API. This is used for every
245 // class so we have this helper function to save template instantiations and 300 // class so we have this helper function to save template instantiations and
246 // typing. 301 // typing.
247 class PPAPI_THUNK_EXPORT EnterResourceCreation 302 class PPAPI_THUNK_EXPORT EnterResourceCreation
248 : public EnterFunction<ResourceCreationAPI> { 303 : public EnterFunction<ResourceCreationAPI> {
249 public: 304 public:
250 EnterResourceCreation(PP_Instance instance); 305 EnterResourceCreation(PP_Instance instance);
251 ~EnterResourceCreation(); 306 ~EnterResourceCreation();
252 }; 307 };
253 308
254 // Simpler wrapper to enter the instance API from proxy code. This is used for 309 // Simpler wrapper to enter the instance API from proxy code. This is used for
255 // many interfaces so we have this helper function to save template 310 // many interfaces so we have this helper function to save template
256 // instantiations and typing. 311 // instantiations and typing.
257 class PPAPI_THUNK_EXPORT EnterInstance 312 class PPAPI_THUNK_EXPORT EnterInstance
258 : public EnterFunction<PPB_Instance_FunctionAPI> { 313 : public EnterFunction<PPB_Instance_FunctionAPI> {
259 public: 314 public:
260 EnterInstance(PP_Instance instance); 315 EnterInstance(PP_Instance instance);
261 EnterInstance(PP_Instance instance, const PP_CompletionCallback& callback); 316 EnterInstance(PP_Instance instance, const PP_CompletionCallback& callback);
262 ~EnterInstance(); 317 ~EnterInstance();
263 }; 318 };
dmichael (off chromium) 2012/04/19 20:02:00 I needed EnterInstanceNoLock to make AudioConfigSh
264 319
320 class PPAPI_THUNK_EXPORT EnterInstanceNoLock
321 : public EnterFunctionNoLock<PPB_Instance_FunctionAPI> {
322 public:
323 EnterInstanceNoLock(PP_Instance instance);
324 EnterInstanceNoLock(PP_Instance instance,
325 const PP_CompletionCallback& callback);
326 ~EnterInstanceNoLock();
327 };
328
329
265 } // namespace thunk 330 } // namespace thunk
266 } // namespace ppapi 331 } // namespace ppapi
267 332
268 #endif // PPAPI_THUNK_ENTER_H_ 333 #endif // PPAPI_THUNK_ENTER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698