| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_CPP_COMPLETION_CALLBACK_H_ | 5 #ifndef PPAPI_CPP_COMPLETION_CALLBACK_H_ |
| 6 #define PPAPI_CPP_COMPLETION_CALLBACK_H_ | 6 #define PPAPI_CPP_COMPLETION_CALLBACK_H_ |
| 7 | 7 |
| 8 #include "ppapi/c/pp_completion_callback.h" | 8 #include "ppapi/c/pp_completion_callback.h" |
| 9 #include "ppapi/c/pp_errors.h" |
| 9 #include "ppapi/cpp/logging.h" | 10 #include "ppapi/cpp/logging.h" |
| 10 #include "ppapi/cpp/non_thread_safe_ref_count.h" | 11 #include "ppapi/cpp/non_thread_safe_ref_count.h" |
| 11 | 12 |
| 12 namespace pp { | 13 namespace pp { |
| 13 | 14 |
| 14 // A CompletionCallback provides a wrapper around PP_CompletionCallback. | 15 // A CompletionCallback provides a wrapper around PP_CompletionCallback. |
| 15 class CompletionCallback { | 16 class CompletionCallback { |
| 16 public: | 17 public: |
| 17 // Use this special constructor to create a 'blocking' CompletionCallback | 18 // Use this special constructor to create a 'blocking' CompletionCallback |
| 18 // that may be passed to a method to indicate that the calling thread should | 19 // that may be passed to a method to indicate that the calling thread should |
| 19 // be blocked until the asynchronous operation corresponding to the method | 20 // be blocked until the asynchronous operation corresponding to the method |
| 20 // completes. | 21 // completes. |
| 21 struct Block {}; | 22 struct Block {}; |
| 22 CompletionCallback(Block) { | 23 CompletionCallback(Block) { |
| 23 cc_ = PP_BlockUntilComplete(); | 24 cc_ = PP_BlockUntilComplete(); |
| 24 } | 25 } |
| 25 | 26 |
| 26 CompletionCallback(PP_CompletionCallback_Func func, void* user_data) { | 27 CompletionCallback(PP_CompletionCallback_Func func, void* user_data) { |
| 27 cc_ = PP_MakeCompletionCallback(func, user_data); | 28 cc_ = PP_MakeCompletionCallback(func, user_data); |
| 28 } | 29 } |
| 29 | 30 |
| 31 CompletionCallback(PP_CompletionCallback_Func func, void* user_data, |
| 32 int32_t flags) { |
| 33 cc_ = PP_MakeCompletionCallback(func, user_data); |
| 34 cc_.flags = flags; |
| 35 } |
| 36 |
| 37 void set_flags(int32_t flags) { cc_.flags = flags; } |
| 38 |
| 30 // Call this method to explicitly run the CompletionCallback. Normally, the | 39 // Call this method to explicitly run the CompletionCallback. Normally, the |
| 31 // system runs a CompletionCallback after an asynchronous operation | 40 // system runs a CompletionCallback after an asynchronous operation |
| 32 // completes, but programs may wish to run the CompletionCallback manually | 41 // completes, but programs may wish to run the CompletionCallback manually |
| 33 // in order to reuse the same code paths. | 42 // in order to reuse the same code paths. |
| 34 void Run(int32_t result) { | 43 void Run(int32_t result) { |
| 35 PP_DCHECK(cc_.func); | 44 PP_DCHECK(cc_.func); |
| 36 PP_RunCompletionCallback(&cc_, result); | 45 PP_RunCompletionCallback(&cc_, result); |
| 37 } | 46 } |
| 38 | 47 |
| 48 bool IsOptional() const { |
| 49 return (cc_.func == NULL || |
| 50 (cc_.flags & PP_COMPLETIONCALLBACK_FLAG_OPTIONAL) != 0); |
| 51 } |
| 52 |
| 39 const PP_CompletionCallback& pp_completion_callback() const { return cc_; } | 53 const PP_CompletionCallback& pp_completion_callback() const { return cc_; } |
| 54 int32_t flags() const { return cc_.flags; } |
| 55 |
| 56 // Use this when implementing functions taking callbacks. |
| 57 // If the callback is required and |result| indicates that it has not |
| 58 // been scheduled, it will be forced on the main thread. |
| 59 // |
| 60 // EXAMPLE USAGE: |
| 61 // |
| 62 // int32_t OpenURL(pp::URLLoader* loader, |
| 63 // pp::URLRequestInfo* url_request_info, |
| 64 // const CompletionCallback& cc) { |
| 65 // if (loader == NULL || url_request_info == NULL) |
| 66 // return cc.MayForce(PP_ERROR_BADRESOURCE); |
| 67 // return loader->Open(*loader, *url_request_info, cc); |
| 68 // } |
| 69 // |
| 70 int32_t MayForce(int32_t result) const { |
| 71 if (result == PP_OK_COMPLETIONPENDING || IsOptional()) |
| 72 return result; |
| 73 Module::Get()->core()->CallOnMainThread(0, *this, result); |
| 74 return PP_OK_COMPLETIONPENDING; |
| 75 } |
| 40 | 76 |
| 41 protected: | 77 protected: |
| 42 PP_CompletionCallback cc_; | 78 PP_CompletionCallback cc_; |
| 43 }; | 79 }; |
| 44 | 80 |
| 45 // CompletionCallbackFactory<T> may be used to create CompletionCallback | 81 // CompletionCallbackFactory<T> may be used to create CompletionCallback |
| 46 // objects that are bound to member functions. | 82 // objects that are bound to member functions. |
| 47 // | 83 // |
| 48 // If a factory is destroyed, then any pending callbacks will be cancelled | 84 // If a factory is destroyed, then any pending callbacks will be cancelled |
| 49 // preventing any bound member functions from being called. The CancelAll | 85 // preventing any bound member functions from being called. The CancelAll |
| (...skipping 10 matching lines...) Expand all Loading... |
| 60 // CallOnMainThread. | 96 // CallOnMainThread. |
| 61 // | 97 // |
| 62 // EXAMPLE USAGE: | 98 // EXAMPLE USAGE: |
| 63 // | 99 // |
| 64 // class MyHandler { | 100 // class MyHandler { |
| 65 // public: | 101 // public: |
| 66 // MyHandler() : factory_(this), offset_(0) { | 102 // MyHandler() : factory_(this), offset_(0) { |
| 67 // } | 103 // } |
| 68 // | 104 // |
| 69 // void ProcessFile(const FileRef& file) { | 105 // void ProcessFile(const FileRef& file) { |
| 70 // CompletionCallback cc = factory_.NewCallback(&MyHandler::DidOpen); | 106 // CompletionCallback cc = factory_.NewRequiredCallback( |
| 107 // &MyHandler::DidOpen); |
| 71 // int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); | 108 // int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); |
| 72 // if (rv != PP_OK_COMPLETIONPENDING) | 109 // CHECK(rv == PP_OK_COMPLETIONPENDING); |
| 73 // cc.Run(rv); | |
| 74 // } | 110 // } |
| 75 // | 111 // |
| 76 // private: | 112 // private: |
| 77 // CompletionCallback NewCallback() { | 113 // CompletionCallback NewCallback() { |
| 78 // return factory_.NewCallback(&MyHandler::DidCompleteIO); | 114 // return factory_.NewCallback(&MyHandler::DidCompleteIO); |
| 79 // } | 115 // } |
| 80 // | 116 // |
| 81 // void DidOpen(int32_t result) { | 117 // void DidOpen(int32_t result) { |
| 82 // if (result == PP_OK) { | 118 // if (result == PP_OK) { |
| 83 // // The file is open, and we can begin reading. | 119 // // The file is open, and we can begin reading. |
| 84 // offset_ = 0; | 120 // offset_ = 0; |
| 85 // ReadMore(); | 121 // ReadMore(); |
| 86 // } else { | 122 // } else { |
| 87 // // Failed to open the file with error given by 'result'. | 123 // // Failed to open the file with error given by 'result'. |
| 88 // } | 124 // } |
| 89 // } | 125 // } |
| 90 // | 126 // |
| 91 // void DidRead(int32_t result) { | 127 // void DidRead(int32_t result) { |
| 92 // if (result > 0) { | 128 // if (result > 0) { |
| 93 // // buf_ now contains 'result' number of bytes from the file. | 129 // // buf_ now contains 'result' number of bytes from the file. |
| 94 // ProcessBytes(buf_, result); | 130 // ProcessBytes(buf_, result); |
| 95 // offset_ += result; | 131 // offset_ += result; |
| 96 // ReadMore(); | 132 // ReadMore(); |
| 97 // } else { | 133 // } else { |
| 98 // // Done reading (possibly with an error given by 'result'). | 134 // // Done reading (possibly with an error given by 'result'). |
| 99 // } | 135 // } |
| 100 // } | 136 // } |
| 101 // | 137 // |
| 102 // void ReadMore() { | 138 // void ReadMore() { |
| 103 // CompletionCallback cc = factory_.NewCallback(&MyHandler::DidRead); | 139 // CompletionCallback cc = |
| 140 // factory_.NewOptionalCallback(&MyHandler::DidRead); |
| 104 // int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), | 141 // int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), |
| 105 // cc.pp_completion_callback()); | 142 // cc.pp_completion_callback()); |
| 106 // if (rv != PP_OK_COMPLETIONPENDING) | 143 // if (rv != PP_OK_COMPLETIONPENDING) |
| 107 // cc.Run(rv); | 144 // cc.Run(rv); |
| 108 // } | 145 // } |
| 109 // | 146 // |
| 110 // void ProcessBytes(const char* bytes, int32_t length) { | 147 // void ProcessBytes(const char* bytes, int32_t length) { |
| 111 // // Do work ... | 148 // // Do work ... |
| 112 // } | 149 // } |
| 113 // | 150 // |
| (...skipping 24 matching lines...) Expand all Loading... |
| 138 void Initialize(T* object) { | 175 void Initialize(T* object) { |
| 139 PP_DCHECK(object); | 176 PP_DCHECK(object); |
| 140 PP_DCHECK(!object_); // May only initialize once! | 177 PP_DCHECK(!object_); // May only initialize once! |
| 141 object_ = object; | 178 object_ = object; |
| 142 } | 179 } |
| 143 | 180 |
| 144 T* GetObject() { | 181 T* GetObject() { |
| 145 return object_; | 182 return object_; |
| 146 } | 183 } |
| 147 | 184 |
| 148 // Allocates a new, single-use CompletionCallback. The CompletionCallback | 185 // Methods for allocating new, single-use CompletionCallbacks. |
| 149 // must be run in order for the memory allocated by NewCallback to be freed. | 186 // The CompletionCallback must be run in order for the memory |
| 150 // If after passing the CompletionCallback to a PPAPI method, the method does | 187 // allocated by the methods to be freed. |
| 151 // not return PP_OK_COMPLETIONPENDING, then you should manually call the | 188 // NewRequiredCallback() creates callbacks that will always run. |
| 152 // CompletionCallback's Run method otherwise memory will be leaked. | 189 // NewOptionalCallback() creates callbacks that might not run if the method |
| 190 // taking them can complete synchronously. Thus, if after passing the |
| 191 // CompletionCallback to a PPAPI method, the method does not return |
| 192 // PP_OK_COMPLETIONPENDING, then you should manually call the |
| 193 // CompletionCallback's Run method, or memory will be leaked. |
| 194 // NewCallback() is equivalent to NewOptionalCallback(). |
| 195 // TODO(polina): update this comment when this is no longer true. |
| 153 | 196 |
| 154 template <typename Method> | 197 template <typename Method> |
| 155 CompletionCallback NewCallback(Method method) { | 198 CompletionCallback NewCallback(Method method) { |
| 156 PP_DCHECK(object_); | 199 PP_DCHECK(object_); |
| 157 return NewCallbackHelper(Dispatcher0<Method>(method)); | 200 return NewCallbackHelper(Dispatcher0<Method>(method)); |
| 158 } | 201 } |
| 159 | 202 |
| 203 template <typename Method> |
| 204 CompletionCallback NewRequiredCallback(Method method) { |
| 205 CompletionCallback cc = NewCallback(method); |
| 206 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 207 return cc; |
| 208 } |
| 209 |
| 210 template <typename Method> |
| 211 CompletionCallback NewOptionalCallback(Method method) { |
| 212 CompletionCallback cc = NewCallback(method); |
| 213 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 214 return cc; |
| 215 } |
| 216 |
| 160 // A copy of "a" will be passed to "method" when the completion callback | 217 // A copy of "a" will be passed to "method" when the completion callback |
| 161 // runs. | 218 // runs. |
| 162 // | 219 // |
| 163 // Method should be of type: | 220 // Method should be of type: |
| 164 // void (T::*)(int32_t result, const A& a) | 221 // void (T::*)(int32_t result, const A& a) |
| 165 // | 222 // |
| 166 template <typename Method, typename A> | 223 template <typename Method, typename A> |
| 167 CompletionCallback NewCallback(Method method, const A& a) { | 224 CompletionCallback NewCallback(Method method, const A& a) { |
| 168 PP_DCHECK(object_); | 225 PP_DCHECK(object_); |
| 169 return NewCallbackHelper(Dispatcher1<Method, A>(method, a)); | 226 return NewCallbackHelper(Dispatcher1<Method, A>(method, a)); |
| 170 } | 227 } |
| 171 | 228 |
| 229 template <typename Method, typename A> |
| 230 CompletionCallback NewRequiredCallback(Method method, const A& a) { |
| 231 CompletionCallback cc = NewCallback(method, a); |
| 232 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 233 return cc; |
| 234 } |
| 235 |
| 236 template <typename Method, typename A> |
| 237 CompletionCallback NewOptionalCallback(Method method, const A& a) { |
| 238 CompletionCallback cc = NewCallback(method, a); |
| 239 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 240 return cc; |
| 241 } |
| 242 |
| 172 // A copy of "a" and "b" will be passed to "method" when the completion | 243 // A copy of "a" and "b" will be passed to "method" when the completion |
| 173 // callback runs. | 244 // callback runs. |
| 174 // | 245 // |
| 175 // Method should be of type: | 246 // Method should be of type: |
| 176 // void (T::*)(int32_t result, const A& a, const B& b) | 247 // void (T::*)(int32_t result, const A& a, const B& b) |
| 177 // | 248 // |
| 178 template <typename Method, typename A, typename B> | 249 template <typename Method, typename A, typename B> |
| 179 CompletionCallback NewCallback(Method method, const A& a, const B& b) { | 250 CompletionCallback NewCallback(Method method, const A& a, const B& b) { |
| 180 PP_DCHECK(object_); | 251 PP_DCHECK(object_); |
| 181 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b)); | 252 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b)); |
| 182 } | 253 } |
| 183 | 254 |
| 255 template <typename Method, typename A, typename B> |
| 256 CompletionCallback NewRequiredCallback(Method method, const A& a, |
| 257 const B& b) { |
| 258 CompletionCallback cc = NewCallback(method, a, b); |
| 259 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 260 return cc; |
| 261 } |
| 262 |
| 263 template <typename Method, typename A, typename B> |
| 264 CompletionCallback NewOptionalCallback(Method method, const A& a, |
| 265 const B& b) { |
| 266 CompletionCallback cc = NewCallback(method, a, b); |
| 267 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 268 return cc; |
| 269 } |
| 270 |
| 184 private: | 271 private: |
| 185 class BackPointer { | 272 class BackPointer { |
| 186 public: | 273 public: |
| 187 typedef CompletionCallbackFactory<T, RefCount> FactoryType; | 274 typedef CompletionCallbackFactory<T, RefCount> FactoryType; |
| 188 | 275 |
| 189 BackPointer(FactoryType* factory) | 276 BackPointer(FactoryType* factory) |
| 190 : factory_(factory) { | 277 : factory_(factory) { |
| 191 } | 278 } |
| 192 | 279 |
| 193 void AddRef() { | 280 void AddRef() { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 CompletionCallbackFactory(const CompletionCallbackFactory&); | 392 CompletionCallbackFactory(const CompletionCallbackFactory&); |
| 306 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); | 393 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); |
| 307 | 394 |
| 308 T* object_; | 395 T* object_; |
| 309 BackPointer* back_pointer_; | 396 BackPointer* back_pointer_; |
| 310 }; | 397 }; |
| 311 | 398 |
| 312 } // namespace pp | 399 } // namespace pp |
| 313 | 400 |
| 314 #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_ | 401 #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_ |
| OLD | NEW |