Home | History | Annotate | Download | only in weak_ref
      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