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 |