1 : /* -*- c++ -*- */
2 : /*
3 : * Copyright (c) 2011 The Native Client 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 0 : template <typename R> class WeakRefAutoAbandonWrapper {
83 : public:
84 : WeakRefAutoAbandonWrapper(void (*callback_fn)(R* raw_data,
85 : int32_t err),
86 0 : R* raw_data)
87 : : orig_callback_fn(callback_fn),
88 0 : 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 0 : int32_t err) {
103 0 : nacl::scoped_ptr<WeakRefAutoAbandonWrapper<R> > p;
104 0 : wr->ReleaseAndUnref(&p);
105 0 : if (p == NULL) {
106 0 : NaClLog2(kPpWeakRefModuleName, 4,
107 : "WeakRefAutoAbandoner: weak ref NULL, anchor was abandoned\n");
108 : return;
109 : }
110 0 : NaClLog2(kPpWeakRefModuleName, 4,
111 : "WeakRefAutoAbandoner: weak ref okay, invoking callback\n");
112 0 : (*p->orig_callback_fn)(p->orig_data.get(), err);
113 0 : 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 0 : R* raw_data) {
123 :
124 : WeakRefAutoAbandonWrapper<R>* wref_auto_wrapper =
125 0 : new WeakRefAutoAbandonWrapper<R>(raw_callback_fn, raw_data);
126 :
127 0 : CHECK(wref_auto_wrapper != NULL);
128 :
129 : nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wp =
130 : anchor->MakeWeakRef<WeakRefAutoAbandonWrapper<R> >(
131 0 : wref_auto_wrapper);
132 : void (*weak_ref_auto_abandoner_ptr)(
133 : nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wr,
134 0 : 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 0 : 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 0 : class WeakRefMemberFuncBinder {
158 : public:
159 : WeakRefMemberFuncBinder(E* object,
160 : void (E::*raw_callback_fn)(R* raw_data,
161 : int32_t err),
162 0 : R* raw_data)
163 : : object_(object),
164 : raw_callback_fn_(raw_callback_fn),
165 0 : data_(raw_data) {}
166 0 : void Invoke(int32_t err) {
167 0 : NaClLog2(kPpWeakRefModuleName, 4,
168 : ("WeakRefMemberFuncBinder: Invoke obj 0x%"NACL_PRIxPTR
169 : ", err%"NACL_PRId32"\n"),
170 : reinterpret_cast<uintptr_t>(object_), err);
171 0 : (object_->*raw_callback_fn_)(data_.get(), err);
172 0 : 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 0 : WeakRefMemberFuncBinder<R, E> *binder, int32_t err) {
184 0 : NaClLog2(kPpWeakRefModuleName, 4,
185 : "WeakRefMemberFuncInvoker: %"NACL_PRIxPTR" %"NACL_PRId32"\n",
186 : (uintptr_t) binder,
187 : err);
188 0 : 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 0 : R* raw_data) {
210 0 : NaClLog2(kPpWeakRefModuleName, 4,
211 : "Entered WeakRefNewCallback\n");
212 0 : 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 0 : raw_data);
219 0 : CHECK(binder != NULL);
220 0 : 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 0 : int32_t err) = WeakRefMemberFuncInvoker<R, E>;
226 : return WeakRefNewCallback(anchor, weak_ref_member_func_invoker_ptr,
227 0 : 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 0 : R* raw_data) {
236 0 : NaClLog2(kPpWeakRefModuleName, 4,
237 : "Entered WeakRefCallOnMainThread\n");
238 : pp::CompletionCallback cc =
239 0 : WeakRefNewCallback(anchor, object, raw_callback_fn, raw_data);
240 0 : NaClLog2(kPpWeakRefModuleName, 4,
241 : "WeakRefCallOnMainThread: got cc\n");
242 0 : pp::Module::Get()->core()->CallOnMainThread(
243 : delay_in_milliseconds,
244 : cc,
245 : PP_OK);
246 0 : NaClLog2(kPpWeakRefModuleName, 4,
247 : "WeakRefCallOnMainThread: invoked PP_CallOnMainThread\n");
248 : }
249 :
250 : } // namespace plugin
251 :
252 : #endif
|