1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
6 /* From ppb_message_loop.idl modified Thu May 9 14:59:57 2013. */
8 #ifndef PPAPI_C_PPB_MESSAGE_LOOP_H_
9 #define PPAPI_C_PPB_MESSAGE_LOOP_H_
11 #include "ppapi/c/pp_bool.h"
12 #include "ppapi/c/pp_completion_callback.h"
13 #include "ppapi/c/pp_instance.h"
14 #include "ppapi/c/pp_macros.h"
15 #include "ppapi/c/pp_resource.h"
16 #include "ppapi/c/pp_stdint.h"
18 #define PPB_MESSAGELOOP_INTERFACE_1_0 "PPB_MessageLoop;1.0"
19 #define PPB_MESSAGELOOP_INTERFACE PPB_MESSAGELOOP_INTERFACE_1_0
23 * Defines the PPB_MessageLoop interface.
28 * @addtogroup Interfaces
32 * A message loop allows PPAPI calls to be issued on a thread. You may not
33 * issue any API calls on a thread without creating a message loop. It also
34 * allows you to post work to the message loop for a thread.
36 * To process work posted to the message loop, as well as completion callbacks
37 * for asynchronous operations, you must run the message loop via Run().
39 * Note the system manages the lifetime of the instance (and all associated
40 * resources). If the instance is deleted from the page, background threads may
41 * suddenly see their PP_Resource handles become invalid. In this case, calls
42 * will fail with PP_ERROR_BADRESOURCE. If you need to access data associated
43 * with your instance, you will probably want to create some kind of threadsafe
44 * proxy object that can handle asynchronous destruction of the instance object.
48 * - Create the thread yourself (using pthreads).
49 * - Create the message loop resource.
50 * - Pass the message loop resource to your thread's main function.
51 * - Call PostWork() on the message loop to run functions on the thread.
53 * From the background thread's main function:
54 * - Call AttachToCurrentThread() with the message loop resource.
55 * - Call Run() with the message loop resource.
57 * Your callbacks should look like this:
59 * void DoMyWork(void* user_data, int32_t status) {
60 * if (status != PP_OK) {
61 * Cleanup(); // e.g. free user_data.
67 * For a C++ example, see ppapi/utility/threading/simple_thread.h
69 * (You can also create the message loop resource on the background thread,
70 * but then the main thread will have no reference to it should you want to
76 * The main thread has an implicitly created message loop. The main thread is
77 * the thread where PPP_InitializeModule and PPP_Instance functions are called.
78 * You can retrieve a reference to this message loop by calling
79 * GetForMainThread() or, if your code is on the main thread,
80 * GetForCurrentThread() will also work.
82 * Some special threads created by the system can not have message loops. In
83 * particular, the background thread created for audio processing has this
84 * requirement because it's intended to be highly responsive to keep up with
85 * the realtime requirements of audio processing. You can not make PPAPI calls
88 * Once you associate a message loop with a thread, you don't have to keep a
89 * reference to it. The system will hold a reference to the message loop for as
90 * long as the thread is running. The current message loop can be retrieved
91 * using the GetCurrent() function.
93 * It is legal to create threads in your plugin without message loops, but
94 * PPAPI calls will fail unless explicitly noted in the documentation.
96 * You can create a message loop object on a thread and never actually run the
97 * message loop. This will allow you to call blocking PPAPI calls (via
98 * PP_BlockUntilComplete()). If you make any asynchronous calls, the callbacks
99 * from those calls will be queued in the message loop and never run. The same
100 * thing will happen if work is scheduled after the message loop exits and
101 * the message loop is not run again.
104 * DESTRUCTION AND ERROR HANDLING
106 * Often, your application will associate memory with completion callbacks. For
107 * example, the C++ CompletionCallbackFactory has a small amount of
108 * heap-allocated memory for each callback. This memory will be leaked if the
109 * callback is never run. To avoid this memory leak, you need to be careful
110 * about error handling and shutdown.
112 * There are a number of cases where posted callbacks will never be run:
114 * - You tear down the thread (via pthreads) without "destroying" the message
115 * loop (via PostQuit with should_destroy = PP_TRUE). In this case, any
116 * tasks in the message queue will be lost.
118 * - You create a message loop, post callbacks to it, and never run it.
120 * - You quit the message loop via PostQuit with should_destroy set to
121 * PP_FALSE. In this case, the system will assume the message loop will be
122 * run again later and keep your tasks.
124 * To do proper shutdown, call PostQuit with should_destroy = PP_TRUE. This
125 * will prohibit future work from being posted, and will allow the message loop
126 * to run until all pending tasks are run.
128 * If you post a callback to a message loop that's been destroyed, or to an
129 * invalid message loop, PostWork will return an error and will not run the
130 * callback. This is true even for callbacks with the "required" flag set,
131 * since the system may not even know what thread to issue the error callback
134 * Therefore, you should check for errors from PostWork and destroy any
135 * associated memory to avoid leaks. If you're using the C++
136 * CompletionCallbackFactory, use the following pattern:
138 * pp::CompletionCallback callback = factory_.NewOptionalCallback(...);
139 * int32_t result = message_loop.PostWork(callback);
140 * if (result != PP_OK)
141 * callback.Run(result);
143 * This will run the callback with an error value, and assumes that the
144 * implementation of your callback checks the "result" argument and returns
145 * immediately on error.
147 struct PPB_MessageLoop_1_0
{
149 * Creates a message loop resource.
151 * This may be called from any thread. After your thread starts but before
152 * issuing any other PPAPI calls on it, you must associate it with a message
153 * loop by calling AttachToCurrentThread.
155 PP_Resource (*Create
)(PP_Instance instance
);
157 * Returns a resource identifying the message loop for the main thread. The
158 * main thread always has a message loop created by the system.
160 PP_Resource (*GetForMainThread
)(void);
162 * Returns a reference to the PPB_MessageLoop object attached to the current
163 * thread. If there is no attached message loop, the return value will be 0.
165 PP_Resource (*GetCurrent
)(void);
167 * Sets the given message loop resource as being the associated message loop
168 * for the currently running thread.
170 * You must call this function exactly once on a thread before making any
171 * PPAPI calls. A message loop can only be attached to one thread, and the
172 * message loop can not be changed later. The message loop will be attached
173 * as long as the thread is running or until you quit with should_destroy
176 * If this function fails, attempting to run the message loop will fail.
177 * Note that you can still post work to the message loop: it will get queued
178 * up should the message loop eventually be successfully attached and run.
181 * - PP_OK: The message loop was successfully attached to the thread and is
183 * - PP_ERROR_BADRESOURCE: The given message loop resource is invalid.
184 * - PP_ERROR_INPROGRESS: The current thread already has a message loop
185 * attached. This will always be the case for the main thread, which has
186 * an implicit system-created message loop attached.
187 * - PP_ERROR_WRONG_THREAD: The current thread type can not have a message
188 * loop attached to it. See the interface level discussion about these
189 * special threads, which include realtime audio threads.
191 int32_t (*AttachToCurrentThread
)(PP_Resource message_loop
);
193 * Runs the thread message loop. Running the message loop is required for you
194 * to get issued completion callbacks on the thread.
196 * The message loop identified by the argument must have been previously
197 * successfully attached to the current thread.
199 * You may not run nested message loops. Since the main thread has an
200 * implicit message loop that the system runs, you may not call Run on the
204 * - PP_OK: The message loop was successfully run. Note that on
205 * success, the message loop will only exit when you call PostQuit().
206 * - PP_ERROR_BADRESOURCE: The given message loop resource is invalid.
207 * - PP_ERROR_WRONG_THREAD: You are attempting to run a message loop that
208 * has not been successfully attached to the current thread. Call
209 * AttachToCurrentThread().
210 * - PP_ERROR_INPROGRESS: You are attempting to call Run in a nested
211 * fashion (Run is already on the stack). This will occur if you attempt
212 * to call run on the main thread's message loop (see above).
214 int32_t (*Run
)(PP_Resource message_loop
);
216 * Schedules work to run on the given message loop. This may be called from
217 * any thread. Posted work will be executed in the order it was posted when
218 * the message loop is Run().
220 * @param message_loop The message loop resource.
222 * @param callback The completion callback to execute from the message loop.
224 * @param delay_ms The number of milliseconds to delay execution of the given
225 * completion callback. Passing 0 means it will get queued normally and
229 * The completion callback will be called with PP_OK as the "result" parameter
230 * if it is run normally. It is good practice to check for PP_OK and return
233 * The "required" flag on the completion callback is ignored. If there is an
234 * error posting your callback, the error will be returned from PostWork and
235 * the callback will never be run (because there is no appropriate place to
236 * run your callback with an error without causing unexpected threading
237 * problems). If you associate memory with the completion callback (for
238 * example, you're using the C++ CompletionCallbackFactory), you will need to
239 * free this or manually run the callback. See "Destruction and error
243 * You can call this function before the message loop has started and the
244 * work will get queued until the message loop is run. You can also post
245 * work after the message loop has exited as long as should_destroy was
246 * PP_FALSE. It will be queued until the next invocation of Run().
249 * - PP_OK: The work was posted to the message loop's queue. As described
250 * above, this does not mean that the work has been or will be executed
251 * (if you never run the message loop after posting).
252 * - PP_ERROR_BADRESOURCE: The given message loop resource is invalid.
253 * - PP_ERROR_BADARGUMENT: The function pointer for the completion callback
254 * is null (this will be the case if you pass PP_BlockUntilComplete()).
255 * - PP_ERROR_FAILED: The message loop has been destroyed.
257 int32_t (*PostWork
)(PP_Resource message_loop
,
258 struct PP_CompletionCallback callback
,
261 * Posts a quit message to the given message loop's work queue. Work posted
262 * before that point will be processed before quitting.
264 * This may be called on the message loop registered for the current thread,
265 * or it may be called on the message loop registered for another thread. It
266 * is an error to attempt to PostQuit() the main thread loop.
268 * @param should_destroy Marks the message loop as being in a destroyed state
269 * and prevents further posting of messages.
271 * If you quit a message loop without setting should_destroy, it will still
272 * be attached to the thread and you can still run it again by calling Run()
273 * again. If you destroy it, it will be detached from the current thread.
276 * - PP_OK: The request to quit was successfully posted.
277 * - PP_ERROR_BADRESOURCE: The message loop was invalid.
278 * - PP_ERROR_WRONG_THREAD: You are attempting to quit the main thread.
279 * The main thread's message loop is managed by the system and can't be
282 int32_t (*PostQuit
)(PP_Resource message_loop
, PP_Bool should_destroy
);
285 typedef struct PPB_MessageLoop_1_0 PPB_MessageLoop
;
290 #endif /* PPAPI_C_PPB_MESSAGE_LOOP_H_ */