- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / native_client / src / trusted / weak_ref / call_on_main_thread.h
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