| OLD | NEW |
| (Empty) |
| 1 /* -*- c++ -*- */ | |
| 2 /* | |
| 3 * Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 // EXAMPLE USAGE | |
| 9 // | |
| 10 // class PluginReverseInterface { | |
| 11 // public: | |
| 12 // PluginReverseInterface(...) : anchor_(new nacl::WeakRefAnchor); | |
| 13 // ~PluginReverseInterface() { anchor_->Abandon(); } | |
| 14 // void Log(nacl::string message) { | |
| 15 // LogContinuation* continuation = new LogContinuation(message); | |
| 16 // plugin::WeakRefCallOnMainThread(anchor_, 0 /* ms delay */, | |
| 17 // this, &PluginReverseInterface::Log_cont, | |
| 18 // continuation); | |
| 19 // } | |
| 20 // void Log_cont(LogContinuation* cont, int32_t result) { | |
| 21 // plugin_->browser_interface()->AddToConsole(plugin_->instance_id(), | |
| 22 // cont->message); | |
| 23 // delete cont; | |
| 24 // } | |
| 25 // private: | |
| 26 // nacl::WeakRefAnchor* anchor_; | |
| 27 // } | |
| 28 | |
| 29 #ifndef NATIVE_CLIENT_SRC_TRUSTED_WEAK_REF_CALL_ON_MAIN_THREAD_H_ | |
| 30 #define NATIVE_CLIENT_SRC_TRUSTED_WEAK_REF_CALL_ON_MAIN_THREAD_H_ | |
| 31 | |
| 32 #include "native_client/src/trusted/weak_ref/weak_ref.h" | |
| 33 | |
| 34 #include "native_client/src/include/nacl_scoped_ptr.h" | |
| 35 #include "native_client/src/include/nacl_compiler_annotations.h" | |
| 36 #include "native_client/src/include/portability.h" | |
| 37 | |
| 38 #include "ppapi/c/pp_errors.h" // for PP_OK | |
| 39 #include "ppapi/cpp/completion_callback.h" // for pp::CompletionCallback | |
| 40 #include "ppapi/cpp/core.h" // for pp:: | |
| 41 #include "ppapi/cpp/module.h" // for pp::Module | |
| 42 | |
| 43 namespace plugin { | |
| 44 | |
| 45 // A typesafe utility to schedule a completion callback using weak | |
| 46 // references. The callback function callback_fn is invoked | |
| 47 // regardless of whether the anchor has been abandoned, since | |
| 48 // callback_fn takes a WeakRef<R>* as argument. The intention is that | |
| 49 // such callbacks, even deprived of any of its arguments (which has | |
| 50 // been deleted), may wish to do some cleanup / log a message. | |
| 51 | |
| 52 static char const* const kPpWeakRefModuleName = "pp_weak_ref"; | |
| 53 | |
| 54 template <typename R> pp::CompletionCallback WeakRefNewCallback( | |
| 55 nacl::WeakRefAnchor* anchor, | |
| 56 void callback_fn(nacl::WeakRef<R>* weak_data, int32_t err), | |
| 57 R* raw_data) { | |
| 58 nacl::WeakRef<R>* wp = anchor->MakeWeakRef<R>(raw_data); | |
| 59 // TODO(bsy): explore using another template to eliminate the | |
| 60 // following cast, making things completely typesafe. | |
| 61 pp::CompletionCallback cc_nrvo( | |
| 62 reinterpret_cast<void (*)(void*, int32_t)>( | |
| 63 callback_fn), | |
| 64 reinterpret_cast<void*>(wp)); | |
| 65 return cc_nrvo; | |
| 66 } | |
| 67 | |
| 68 template <typename R> void WeakRefCallOnMainThread( | |
| 69 nacl::WeakRefAnchor* anchor, | |
| 70 int32_t delay_in_milliseconds, | |
| 71 void callback_fn(nacl::WeakRef<R>* weak_data, int32_t err), | |
| 72 R* raw_data) { | |
| 73 pp::CompletionCallback cc = | |
| 74 WeakRefNewCallback(anchor, callback_fn, raw_data, &cc); | |
| 75 | |
| 76 pp::Module::Get()->core()->CallOnMainThread( | |
| 77 delay_in_milliseconds, | |
| 78 cc, | |
| 79 PP_OK); | |
| 80 } | |
| 81 | |
| 82 template <typename R> class WeakRefAutoAbandonWrapper { | |
| 83 public: | |
| 84 WeakRefAutoAbandonWrapper(void (*callback_fn)(R* raw_data, | |
| 85 int32_t err), | |
| 86 R* raw_data) | |
| 87 : orig_callback_fn(callback_fn), | |
| 88 orig_data(raw_data) {} | |
| 89 | |
| 90 void (*orig_callback_fn)(R* raw_data, int32_t err); | |
| 91 nacl::scoped_ptr<R> orig_data; | |
| 92 }; | |
| 93 | |
| 94 /* | |
| 95 * It would be nice if the function had the right type signature, | |
| 96 * i.e., void WeakRefAutoAbandoner(void *wr_data, int32_t) but then | |
| 97 * the formal argument list would not use the typename template | |
| 98 * argument R, making template resolution impossible. | |
| 99 */ | |
| 100 template <typename R> void WeakRefAutoAbandoner( | |
| 101 nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wr, | |
| 102 int32_t err) { | |
| 103 nacl::scoped_ptr<WeakRefAutoAbandonWrapper<R> > p; | |
| 104 wr->ReleaseAndUnref(&p); | |
| 105 if (p == NULL) { | |
| 106 NaClLog2(kPpWeakRefModuleName, 4, | |
| 107 "WeakRefAutoAbandoner: weak ref NULL, anchor was abandoned\n"); | |
| 108 return; | |
| 109 } | |
| 110 NaClLog2(kPpWeakRefModuleName, 4, | |
| 111 "WeakRefAutoAbandoner: weak ref okay, invoking callback\n"); | |
| 112 (*p->orig_callback_fn)(p->orig_data.get(), err); | |
| 113 return; | |
| 114 } | |
| 115 | |
| 116 // A typesafe utility to schedule a completion callback using weak | |
| 117 // references. The callback function raw_callback_fn takes an R* as | |
| 118 // argument, and is not invoked if the anchor has been abandoned. | |
| 119 template <typename R> pp::CompletionCallback WeakRefNewCallback( | |
| 120 nacl::WeakRefAnchor* anchor, | |
| 121 void (*raw_callback_fn)(R* raw_data, int32_t err), | |
| 122 R* raw_data) { | |
| 123 | |
| 124 WeakRefAutoAbandonWrapper<R>* wref_auto_wrapper = | |
| 125 new WeakRefAutoAbandonWrapper<R>(raw_callback_fn, raw_data); | |
| 126 | |
| 127 CHECK(wref_auto_wrapper != NULL); | |
| 128 | |
| 129 nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wp = | |
| 130 anchor->MakeWeakRef<WeakRefAutoAbandonWrapper<R> >( | |
| 131 wref_auto_wrapper); | |
| 132 void (*weak_ref_auto_abandoner_ptr)( | |
| 133 nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wr, | |
| 134 int32_t err) = WeakRefAutoAbandoner<R>; | |
| 135 // TODO(bsy): see above | |
| 136 pp::CompletionCallback cc_nrvo( | |
| 137 reinterpret_cast<void (*)(void*, int32_t)>(weak_ref_auto_abandoner_ptr), | |
| 138 reinterpret_cast<void*>(wp)); | |
| 139 return cc_nrvo; | |
| 140 } | |
| 141 | |
| 142 template <typename R> void WeakRefCallOnMainThread( | |
| 143 nacl::WeakRefAnchor* anchor, | |
| 144 int32_t delay_in_milliseconds, | |
| 145 void raw_callback_fn(R* raw_data, int32_t err), | |
| 146 R* raw_data) { | |
| 147 pp::CompletionCallback cc = | |
| 148 WeakRefNewCallback(anchor, raw_callback_fn, raw_data, &cc); | |
| 149 pp::Module::Get()->core()->CallOnMainThread( | |
| 150 delay_in_milliseconds, | |
| 151 cc, | |
| 152 PP_OK); | |
| 153 } | |
| 154 | |
| 155 | |
| 156 template <typename R, typename E> | |
| 157 class WeakRefMemberFuncBinder { | |
| 158 public: | |
| 159 WeakRefMemberFuncBinder(E* object, | |
| 160 void (E::*raw_callback_fn)(R* raw_data, | |
| 161 int32_t err), | |
| 162 R* raw_data) | |
| 163 : object_(object), | |
| 164 raw_callback_fn_(raw_callback_fn), | |
| 165 data_(raw_data) {} | |
| 166 void Invoke(int32_t err) { | |
| 167 NaClLog2(kPpWeakRefModuleName, 4, | |
| 168 ("WeakRefMemberFuncBinder: Invoke obj 0x%" NACL_PRIxPTR | |
| 169 ", err%" NACL_PRId32 "\n"), | |
| 170 reinterpret_cast<uintptr_t>(object_), err); | |
| 171 (object_->*raw_callback_fn_)(data_.get(), err); | |
| 172 NaClLog2(kPpWeakRefModuleName, 4, | |
| 173 "WeakRefMemberFuncBinder: done\n"); | |
| 174 } | |
| 175 private: | |
| 176 E* object_; | |
| 177 void (E::*raw_callback_fn_)(R* raw_data, int32_t err); | |
| 178 nacl::scoped_ptr<R> data_; | |
| 179 }; | |
| 180 | |
| 181 template <typename R, typename E> | |
| 182 void WeakRefMemberFuncInvoker( | |
| 183 WeakRefMemberFuncBinder<R, E> *binder, int32_t err) { | |
| 184 NaClLog2(kPpWeakRefModuleName, 4, | |
| 185 "WeakRefMemberFuncInvoker: %" NACL_PRIxPTR " %" NACL_PRId32 "\n", | |
| 186 (uintptr_t) binder, | |
| 187 err); | |
| 188 binder->Invoke(err); | |
| 189 // delete binder not needed, since WeakRefAutoAbandoner holds binder | |
| 190 // in a scoped_ptr and will automatically delete on scope exit. | |
| 191 } | |
| 192 | |
| 193 | |
| 194 // A typesafe utility to schedule a completion callback using weak | |
| 195 // references, where the callback function is a member function. The | |
| 196 // member function must take only a raw argument data pointer and a | |
| 197 // completion status as formal parameters. The lifetime of the | |
| 198 // |object| and |raw_callback_fn| must be at least that of |anchor|. | |
| 199 // Typically |object| is just the object that controls the |anchor|, | |
| 200 // though it may be some sub-object that is contained within the | |
| 201 // actual controlling object. If the |anchor| is abandoned, the | |
| 202 // |raw_data| argument is deleted and the |raw_callback_fn| will not | |
| 203 // be invoked. | |
| 204 template <typename R, typename E> | |
| 205 pp::CompletionCallback WeakRefNewCallback( | |
| 206 nacl::WeakRefAnchor* anchor, | |
| 207 E* object, | |
| 208 void (E::*raw_callback_fn)(R* raw_data, int32_t err), | |
| 209 R* raw_data) { | |
| 210 NaClLog2(kPpWeakRefModuleName, 4, | |
| 211 "Entered WeakRefNewCallback\n"); | |
| 212 NaClLog2(kPpWeakRefModuleName, 4, | |
| 213 "object 0x%" NACL_PRIxPTR "\n", | |
| 214 reinterpret_cast<uintptr_t>(object)); | |
| 215 WeakRefMemberFuncBinder<R, E>* binder = | |
| 216 new WeakRefMemberFuncBinder<R, E>(object, | |
| 217 raw_callback_fn, | |
| 218 raw_data); | |
| 219 CHECK(binder != NULL); | |
| 220 NaClLog2(kPpWeakRefModuleName, 4, | |
| 221 "WeakRefNewCallback: binder %" NACL_PRIxPTR "\n", | |
| 222 (uintptr_t) binder); | |
| 223 void (*weak_ref_member_func_invoker_ptr)( | |
| 224 WeakRefMemberFuncBinder<R, E>* binder, | |
| 225 int32_t err) = WeakRefMemberFuncInvoker<R, E>; | |
| 226 return WeakRefNewCallback(anchor, weak_ref_member_func_invoker_ptr, | |
| 227 binder); | |
| 228 } | |
| 229 | |
| 230 template <typename R, typename E> void WeakRefCallOnMainThread( | |
| 231 nacl::WeakRefAnchor* anchor, | |
| 232 int32_t delay_in_milliseconds, | |
| 233 E* object, | |
| 234 void (E::*raw_callback_fn)(R* raw_data, int32_t err), | |
| 235 R* raw_data) { | |
| 236 NaClLog2(kPpWeakRefModuleName, 4, | |
| 237 "Entered WeakRefCallOnMainThread\n"); | |
| 238 pp::CompletionCallback cc = | |
| 239 WeakRefNewCallback(anchor, object, raw_callback_fn, raw_data); | |
| 240 NaClLog2(kPpWeakRefModuleName, 4, | |
| 241 "WeakRefCallOnMainThread: got cc\n"); | |
| 242 pp::Module::Get()->core()->CallOnMainThread( | |
| 243 delay_in_milliseconds, | |
| 244 cc, | |
| 245 PP_OK); | |
| 246 NaClLog2(kPpWeakRefModuleName, 4, | |
| 247 "WeakRefCallOnMainThread: invoked PP_CallOnMainThread\n"); | |
| 248 } | |
| 249 | |
| 250 } // namespace plugin | |
| 251 | |
| 252 #endif | |
| OLD | NEW |