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 253