summaryrefslogtreecommitdiffstats
path: root/xpcom/threads/nsIEventTarget.idl
blob: 2139dc5ab3858345c49985e2d3253b8a8a9f194b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsISupports.idl"
#include "nsIRunnable.idl"
%{C++
#include "nsCOMPtr.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Atomics.h"

class nsITargetShutdownTask;
%}

native alreadyAddRefed_nsIRunnable(already_AddRefed<nsIRunnable>);
[ptr] native nsITargetShutdownTask(nsITargetShutdownTask);

[builtinclass, scriptable, uuid(a03b8b63-af8b-4164-b0e5-c41e8b2b7cfa)]
interface nsIEventTarget : nsISupports
{
  /* until we can get rid of all uses, keep the non-alreadyAddRefed<> version */
%{C++
    nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
      return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
    }
%}

  /**
   * This flag specifies the default mode of event dispatch, whereby the event
   * is simply queued for later processing.  When this flag is specified,
   * dispatch returns immediately after the event is queued.
   */
  const unsigned long DISPATCH_NORMAL = 0;

  // NOTE: 1 used to be DISPATCH_SYNC

  /**
   * This flag specifies that the dispatch is occurring from a running event
   * that was dispatched to the same event target, and that event is about to
   * finish.
   *
   * A thread pool can use this as an optimization hint to not spin up
   * another thread, since the current thread is about to become idle.
   *
   * These events are always async.
   */
  const unsigned long DISPATCH_AT_END = 2;

  /**
   * This flag specifies that the dispatched event may block the thread on
   * which it executes, usually by doing some sort of I/O.  This information
   * may be used by the event target to execute the job on a thread
   * specifically dedicated to doing I/O, leaving other threads available for
   * CPU-intensive work.
   */
  const unsigned long DISPATCH_EVENT_MAY_BLOCK = 4;

  /**
   * This flag specifies that the dispatched event should be delivered to the
   * target thread even if the thread has been configured to block dispatching
   * of runnables. This is generally done for threads which have their own
   * internal event loop, such as thread pools or the timer thread, and will not
   * service runnables dispatched to them until shutdown.
   */
  const unsigned long DISPATCH_IGNORE_BLOCK_DISPATCH = 8;

  /**
   * IsOnCurrentThread() should return true if events dispatched to this target
   * can possibly run on the current thread, and false otherwise. In the case
   * of an nsIEventTarget for a thread pool, it should return true on all
   * threads in the pool. In the case of a non-thread nsIEventTarget such as
   * ThrottledEventQueue, it should return true on the thread where events are
   * expected to be processed, even if no events from the queue are actually
   * being processed right now.
   *
   * When called on an nsISerialEventTarget, IsOnCurrentThread can be used to
   * ensure that no other thread has "ownership" of the event target. As such,
   * it's useful for asserting that an object is only used on a particular
   * thread. IsOnCurrentThread can't guarantee that the current event has been
   * dispatched through a particular event target.
   *
   * The infallible version of IsOnCurrentThread() is optimized to avoid a
   * virtual call for non-thread event targets. Thread targets should set
   * mThread to their virtual PRThread. Non-thread targets should leave
   * mThread null and implement IsOnCurrentThreadInfallible() to
   * return the correct answer.
   *
   * The fallible version of IsOnCurrentThread may return errors, such as during
   * shutdown. If it does not return an error, it should return the same result
   * as the infallible version. The infallible method should return the correct
   * result regardless of whether the fallible method returns an error.
   */
  %{C++
public:
  // Infallible. Defined in nsThreadUtils.cpp. Delegates to
  // IsOnCurrentThreadInfallible when mThread is null.
  bool IsOnCurrentThread();

protected:
  mozilla::Atomic<PRThread*> mThread;

  nsIEventTarget() : mThread(nullptr) {}
  %}
  // Note that this method is protected.  We define it through IDL, rather than
  // in a %{C++ block, to ensure that the correct method indices are recorded
  // for XPConnect purposes.
  [noscript,notxpcom] boolean isOnCurrentThreadInfallible();
  %{C++
public:
  %}

  // Fallible version of IsOnCurrentThread.
  boolean isOnCurrentThread();

  /**
   * Dispatch an event to this event target.  This function may be called from
   * any thread, and it may be called re-entrantly.
   *
   * @param event
   *   The alreadyAddRefed<> event to dispatch.
   *   NOTE that the event will be leaked if it fails to dispatch.
   * @param flags
   *   The flags modifying event dispatch.  The flags are described in detail
   *   below.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched.
   */
  [noscript, binaryname(Dispatch)] void dispatchFromC(in alreadyAddRefed_nsIRunnable event,
                                                      [default(DISPATCH_NORMAL)] in unsigned long flags);
  /**
   * Version of Dispatch to expose to JS, which doesn't require an alreadyAddRefed<>
   * (it will be converted to that internally)
   *
   * @param event
   *   The (raw) event to dispatch.
   * @param flags
   *   The flags modifying event dispatch.  The flags are described in detail
   *   below.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched.
   */
  [binaryname(DispatchFromScript)] void dispatch(in nsIRunnable event, in unsigned long flags);
  /**
   * Dispatch an event to this event target, but do not run it before delay
   * milliseconds have passed.  This function may be called from any thread.
   *
   * @param event
   *   The alreadyAddrefed<> event to dispatch.
   * @param delay
   *   The delay (in ms) before running the event.  If event does not rise to
   *   the top of the event queue before the delay has passed, it will be set
   *   aside to execute once the delay has passed.  Otherwise, it will be
   *   executed immediately.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched, or
   * that delay is zero.
   */
  [noscript] void delayedDispatch(in alreadyAddRefed_nsIRunnable event, in unsigned long delay);

  /**
   * Register an task to be run on this event target when it begins shutting
   * down.  Shutdown tasks may be run in any order, and this function may be
   * called from any thread.
   *
   * The event target may or may not continue accepting events during or after
   * the shutdown task. The precise behaviour here depends on the event target.
   *
   * @param task
   *   The task to be registered to the target thread.
   *   NOTE that unlike `dispatch`, this will not leak the task if it fails.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that task is null.
   * @throws NS_ERROR_NOT_IMPLEMENTED
   *   Indicates that this event target doesn't support shutdown tasks.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is already shutting down, and no longer
   *   accepting events.
   */
  [noscript] void registerShutdownTask(in nsITargetShutdownTask task);

  /**
   * Unregisters an task previously registered with registerShutdownTask.  This
   * function may be called from any thread.
   *
   * @param task
   *   The task previously registered with registerShutdownTask
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that task is null.
   * @throws NS_ERROR_NOT_IMPLEMENTED
   *   Indicates that this event target doesn't support shutdown tasks.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is already shutting down, and no longer
   *   accepting events, or that the shutdown task cannot be found.
   */
  [noscript] void unregisterShutdownTask(in nsITargetShutdownTask task);
};

%{C++
// convenient aliases:
#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL
#define NS_DISPATCH_AT_END nsIEventTarget::DISPATCH_AT_END
#define NS_DISPATCH_EVENT_MAY_BLOCK nsIEventTarget::DISPATCH_EVENT_MAY_BLOCK
#define NS_DISPATCH_IGNORE_BLOCK_DISPATCH nsIEventTarget::DISPATCH_IGNORE_BLOCK_DISPATCH

// Convenient NS_DECL variant that includes some C++-only methods.
#define NS_DECL_NSIEVENTTARGET_FULL                                   \
    NS_DECL_NSIEVENTTARGET                                            \
    /* Avoid hiding these methods */                                  \
    using nsIEventTarget::Dispatch;                                   \
    using nsIEventTarget::IsOnCurrentThread;
%}