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.
4 */
5
6/* From ppb_message_loop.idl modified Thu May  9 14:59:57 2013. */
7
8#ifndef PPAPI_C_PPB_MESSAGE_LOOP_H_
9#define PPAPI_C_PPB_MESSAGE_LOOP_H_
10
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"
17
18#define PPB_MESSAGELOOP_INTERFACE_1_0 "PPB_MessageLoop;1.0"
19#define PPB_MESSAGELOOP_INTERFACE PPB_MESSAGELOOP_INTERFACE_1_0
20
21/**
22 * @file
23 * Defines the PPB_MessageLoop interface.
24 */
25
26
27/**
28 * @addtogroup Interfaces
29 * @{
30 */
31/**
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.
35 *
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().
38 *
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.
45 *
46 * Typical usage:
47 *   On the main thread:
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.
52 *
53 *   From the background thread's main function:
54 *    - Call AttachToCurrentThread() with the message loop resource.
55 *    - Call Run() with the message loop resource.
56 *
57 *   Your callbacks should look like this:
58 *   @code
59 *   void DoMyWork(void* user_data, int32_t status) {
60 *     if (status != PP_OK) {
61 *       Cleanup();  // e.g. free user_data.
62 *       return;
63 *     }
64 *     ... do your work...
65 *   }
66 *   @endcode
67 * For a C++ example, see ppapi/utility/threading/simple_thread.h
68 *
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
71 * call PostWork()).
72 *
73 *
74 * THREAD HANDLING
75 *
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, GetCurrent() will
80 * also work.
81 *
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
86 * from these threads.
87 *
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.
92 *
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.
95 *
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.
102 *
103 *
104 * DESTRUCTION AND ERROR HANDLING
105 *
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.
111 *
112 * There are a number of cases where posted callbacks will never be run:
113 *
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.
117 *
118 *  - You create a message loop, post callbacks to it, and never run it.
119 *
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.
123 *
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.
127 *
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
132 * on.
133 *
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:
137 * @code
138 * pp::CompletionCallback callback = factory_.NewOptionalCallback(...);
139 * int32_t result = message_loop.PostWork(callback);
140 * if (result != PP_OK)
141 *   callback.Run(result);
142 * @endcode
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.
146 */
147struct PPB_MessageLoop_1_0 {
148  /**
149   * Creates a message loop resource.
150   *
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.
154   */
155  PP_Resource (*Create)(PP_Instance instance);
156  /**
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.
159   */
160  PP_Resource (*GetForMainThread)(void);
161  /**
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.
164   */
165  PP_Resource (*GetCurrent)(void);
166  /**
167   * Sets the given message loop resource as being the associated message loop
168   * for the currently running thread.
169   *
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
174   * set to PP_TRUE.
175   *
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.
179   *
180   * @return
181   *   - PP_OK: The message loop was successfully attached to the thread and is
182   *     ready to use.
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.
190   */
191  int32_t (*AttachToCurrentThread)(PP_Resource message_loop);
192  /**
193   * Runs the thread message loop. Running the message loop is required for you
194   * to get issued completion callbacks on the thread.
195   *
196   * The message loop identified by the argument must have been previously
197   * successfully attached to the current thread.
198   *
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
201   * main thread.
202   *
203   * @return
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).
213   */
214  int32_t (*Run)(PP_Resource message_loop);
215  /**
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().
219   *
220   * @param message_loop The message loop resource.
221   *
222   * @param callback The completion callback to execute from the message loop.
223   *
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
226   * executed in order.
227   *
228   *
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
231   * early otherwise.
232   *
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
240   * handling" above.
241   *
242   *
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().
247   *
248   * @return
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.
256   */
257  int32_t (*PostWork)(PP_Resource message_loop,
258                      struct PP_CompletionCallback callback,
259                      int64_t delay_ms);
260  /**
261   * Posts a quit message to the given message loop's work queue. Work posted
262   * before that point will be processed before quitting.
263   *
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.
267   *
268   * @param should_destroy Marks the message loop as being in a destroyed state
269   * and prevents further posting of messages.
270   *
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.
274   *
275   * @return
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
280   *     quit.
281   */
282  int32_t (*PostQuit)(PP_Resource message_loop, PP_Bool should_destroy);
283};
284
285typedef struct PPB_MessageLoop_1_0 PPB_MessageLoop;
286/**
287 * @}
288 */
289
290#endif  /* PPAPI_C_PPB_MESSAGE_LOOP_H_ */
291
292