Componentize component_updater: Copy over test data with executable bit.
[chromium-blink-merge.git] / ppapi / native_client / src / untrusted / nacl_ppapi_util / nacl_ppapi_util.h
blobbbfd8bac39de79848d5db7583e212a178de24e9f
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 */
8 #ifndef NATIVE_CLIENT_SRC_UNTRUSTED_NACL_PPAPI_UTIL_NACL_PPAPI_UTIL_H_
9 #define NATIVE_CLIENT_SRC_UNTRUSTED_NACL_PPAPI_UTIL_NACL_PPAPI_UTIL_H_
11 #include "ppapi/cpp/instance.h"
12 #include "ppapi/cpp/module.h"
13 #include "ppapi/cpp/var.h"
15 #include "native_client/src/include/nacl_base.h"
16 #include "native_client/src/include/nacl_scoped_ptr.h"
17 #include "native_client/src/shared/platform/nacl_sync.h"
18 #include "native_client/src/shared/platform/nacl_sync_checked.h"
19 #include "native_client/src/shared/platform/nacl_sync_raii.h"
21 // TODO(bsy): move weak_ref module to the shared directory
22 #include "native_client/src/trusted/weak_ref/weak_ref.h"
23 #include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h"
25 // The nomenclature used in this file is intended to clarify thinking
26 // about the Pepper "main thread". The "main thread" is really an
27 // interrupt service thread, or an event handler thread, since it is
28 // bad to do blocking operations or execute code that runs for a long
29 // time on it. Event handlers should complete quickly -- possibly
30 // just enqueuing the event for processing by some worker thread --
31 // and return, so that additional event dispatch can occur.
33 // Code that does real work (and tests) should run in a separate,
34 // worker thread. The main event handler thread is where the
35 // post-message handler runs via a pp::Module virtual member function
36 // (HandleMessage), which represents the plugin instance. This plugin
37 // instance can go away at any time, e.g., due to surf-away. Thus,
38 // other threads should not use pointers to the pp::Module, since the
39 // object isn't reference counted (and probably shouldn't be, since
40 // it really have to shut down / clean up when Pepper tells it to),
41 // and main thread-only operations such as PostMessage or
42 // GetOSFileDescriptor on the FileIO_Dev PP_Resource must not be done
43 // from the worker threads.
45 // Our solution to this is as follows:
47 // The plugin instance object holds a reference to a WeakRefAnchor
48 // object, and the plugin instance object's dtor invokes the Abandon
49 // method on the anchor. Since the nacl::WeakRefAnchor object is
50 // thread-safe and is reference counted, the anchor pointer may be
51 // passed to worker threads. Worker threads are responsible for
52 // maintaining the anchor refcount: each thread would hold a
53 // reference, and must Unref prior to thread exit. The worker threads
54 // can use plugin::WeakRefCallOnMainThread to enqueue continuation
55 // callbacks to run on the main thread -- these will get cancelled if
56 // the WeakRefAnchor was abandoned, which only occurs in the module
57 // object's dtor, which can only run in the main thread. Since the
58 // continuation won't run if the plugin instance is still valid, the
59 // continuation can safely use pointers to the instance to perform
60 // main-thread operations or to run member functions in the test
61 // object or in the module object. The worker thread may hold a
62 // pointer to the plugin instance object in order to schedule
63 // callbacks via plugin::WeakRefCallOnMainThread using a method
64 // pointer, but should not otherwise use the pointer.
66 // So, an operation (test) running on a worker thread must be broken
67 // into separate computation phases according to which thread is
68 // appropriate for invoking which operations. For compute-only phases
69 // or manifest RPCs (which block and also invoke CallOnMainThread),
70 // the computation should occur on the worker thread. When the worker
71 // thread needs to invoke a main-thread-only operation such as
72 // PostMessage, it should use its WeakRefAnchor objecct to schedule a
73 // main thread callback and then wait on a condition variable for the
74 // operation to complete. The main thread callback can invoke the
75 // main-thread-only operation, then signal the condition variable to
76 // wake up the worker thread prior to returning. After the worker
77 // thread wakes up, it can use other synchronization methods to
78 // determine if the worker thread should continue to run or exit
79 // (e.g., if the worker thread is associated with the plugin instance,
80 // then if the main thread work result is NULL, the worker thread
81 // should probably Unref its anchor (and do other cleanup) and exit.
83 namespace nacl_ppapi {
85 template <typename R> class EventThreadWorkStateWrapper; // fwd
87 // the worker thread should own the EventThreadWorkState<R> object
88 template <typename R>
89 class EventThreadWorkState {
90 public:
91 EventThreadWorkState()
92 : done_(false),
93 result_(NULL) {
94 NaClXMutexCtor(&mu_);
95 NaClXCondVarCtor(&cv_);
98 virtual ~EventThreadWorkState() {
99 NaClMutexDtor(&mu_);
100 NaClCondVarDtor(&cv_);
103 // Pass ownership of result into the EventThreadWorkState. The value
104 // of result should be non-NULL to distinguish between
105 // completion/abandonment.
106 void SetResult(R *result) {
107 nacl::MutexLocker take(&mu_);
108 result_.reset(result);
111 // Returns result if callback completed, NULL if abandoned
112 R *WaitForCompletion() {
113 nacl::MutexLocker take(&mu_);
114 while (!done_) {
115 NaClXCondVarWait(&cv_, &mu_);
117 return result_.release();
120 private:
121 friend class EventThreadWorkStateWrapper<R>;
122 void EventThreadWorkDone() {
123 nacl::MutexLocker take(&mu_);
124 done_ = true;
125 NaClXCondVarBroadcast(&cv_);
128 NaClMutex mu_;
129 NaClCondVar cv_;
130 bool done_;
131 nacl::scoped_ptr<R> result_;
133 DISALLOW_COPY_AND_ASSIGN(EventThreadWorkState);
137 // Wrapper around EventThreadWorkState<R> or subclass thereof. The
138 // wrapper object should be created by a worker thread and the
139 // ownership passed into the COMT machinery, to be used and deleted on
140 // the main thread. This object is automatically deleted by the
141 // WeakRef machinery when the callback fires, and the dtor will just
142 // signal completion. If the anchor corresponding to the callback had
143 // not been abandoned, then the callback function should invoke
144 // SetResult before returning to pass ownership of a result object (R)
145 // from the main thread to the worker thread.
147 // Subclasses of EventThreadWorkStateWrapper may be used, so that
148 // contained input arguments are automatically deleted when the
149 // callback fires, or input arguments may be stashed in subclasses of
150 // EventThreadWorkState<R>.
151 template <typename R>
152 class EventThreadWorkStateWrapper {
153 public:
154 explicit EventThreadWorkStateWrapper(EventThreadWorkState<R> *ws):
155 ws_(ws) {}
156 virtual ~EventThreadWorkStateWrapper() {
157 ws_->EventThreadWorkDone();
160 void SetResult(R *result) {
161 ws_->SetResult(result);
163 private:
164 EventThreadWorkState<R> *ws_;
166 DISALLOW_COPY_AND_ASSIGN(EventThreadWorkStateWrapper);
169 class VoidResult;
171 extern VoidResult *const g_void_result;
173 class VoidResult {
174 public:
175 VoidResult() {}
176 void *operator new(size_t size) { return g_void_result; }
177 void operator delete(void *p) {}
178 private:
179 DISALLOW_COPY_AND_ASSIGN(VoidResult);
182 // Canonical pointer return value used with SetResult when the main
183 // thread operation does not return a result. The class declaration
184 // is private, so the compiler should refuse to allow the use of the
185 // delete operator.
187 // A plugin instance object should be referred to only from the main
188 // thread. Pointers to the anchor object can be given to worker
189 // thread so they can schedule work on the main thread via COMT.
190 class NaClPpapiPluginInstance : public pp::Instance {
191 public:
192 explicit NaClPpapiPluginInstance(PP_Instance instance);
193 virtual ~NaClPpapiPluginInstance();
194 nacl::WeakRefAnchor* anchor() const { return anchor_; }
195 protected:
196 nacl::WeakRefAnchor* anchor_;
197 DISALLOW_COPY_AND_ASSIGN(NaClPpapiPluginInstance);
200 } // namespace nacl_ppapi
202 #endif