1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim:set ts=2 sw=2 sts=2 et cindent: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsISupports.idl"
8#include "nsIRunnable.idl"
9%{C++
10#include "nsCOMPtr.h"
11#include "mozilla/AlreadyAddRefed.h"
12#include "mozilla/Atomics.h"
13%}
14
15native alreadyAddRefed_nsIRunnable(already_AddRefed<nsIRunnable>);
16
17[builtinclass, scriptable, uuid(a03b8b63-af8b-4164-b0e5-c41e8b2b7cfa)]
18interface nsIEventTarget : nsISupports
19{
20  /* until we can get rid of all uses, keep the non-alreadyAddRefed<> version */
21%{C++
22    nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
23      return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
24    }
25%}
26
27  /**
28   * This flag specifies the default mode of event dispatch, whereby the event
29   * is simply queued for later processing.  When this flag is specified,
30   * dispatch returns immediately after the event is queued.
31   */
32  const unsigned long DISPATCH_NORMAL = 0;
33
34  /**
35   * This flag specifies the synchronous mode of event dispatch, in which the
36   * dispatch method does not return until the event has been processed.
37   *
38   * NOTE: passing this flag to dispatch may have the side-effect of causing
39   * other events on the current thread to be processed while waiting for the
40   * given event to be processed.
41   */
42  const unsigned long DISPATCH_SYNC = 1;
43
44  /**
45   * This flag specifies that the dispatch is occurring from a running event
46   * that was dispatched to the same event target, and that event is about to
47   * finish.
48   *
49   * A thread pool can use this as an optimization hint to not spin up
50   * another thread, since the current thread is about to become idle.
51   *
52   * These events are always async.
53   */
54  const unsigned long DISPATCH_AT_END = 2;
55
56  /**
57   * This flag specifies that the dispatched event may block the thread on
58   * which it executes, usually by doing some sort of I/O.  This information
59   * may be used by the event target to execute the job on a thread
60   * specifically dedicated to doing I/O, leaving other threads available for
61   * CPU-intensive work.
62   */
63  const unsigned long DISPATCH_EVENT_MAY_BLOCK = 4;
64
65  /**
66   * IsOnCurrentThread() should return true if events dispatched to this target
67   * can possibly run on the current thread, and false otherwise. In the case
68   * of an nsIEventTarget for a thread pool, it should return true on all
69   * threads in the pool. In the case of a non-thread nsIEventTarget such as
70   * ThrottledEventQueue, it should return true on the thread where events are
71   * expected to be processed, even if no events from the queue are actually
72   * being processed right now.
73   *
74   * When called on an nsISerialEventTarget, IsOnCurrentThread can be used to
75   * ensure that no other thread has "ownership" of the event target. As such,
76   * it's useful for asserting that an object is only used on a particular
77   * thread. IsOnCurrentThread can't guarantee that the current event has been
78   * dispatched through a particular event target.
79   *
80   * The infallible version of IsOnCurrentThread() is optimized to avoid a
81   * virtual call for non-thread event targets. Thread targets should set
82   * mThread to their virtual PRThread. Non-thread targets should leave
83   * mThread null and implement IsOnCurrentThreadInfallible() to
84   * return the correct answer.
85   *
86   * The fallible version of IsOnCurrentThread may return errors, such as during
87   * shutdown. If it does not return an error, it should return the same result
88   * as the infallible version. The infallible method should return the correct
89   * result regardless of whether the fallible method returns an error.
90   */
91  %{C++
92public:
93  // Infallible. Defined in nsThreadUtils.cpp. Delegates to
94  // IsOnCurrentThreadInfallible when mThread is null.
95  bool IsOnCurrentThread();
96
97protected:
98  mozilla::Atomic<PRThread*> mThread;
99
100  nsIEventTarget() : mThread(nullptr) {}
101  %}
102  // Note that this method is protected.  We define it through IDL, rather than
103  // in a %{C++ block, to ensure that the correct method indices are recorded
104  // for XPConnect purposes.
105  [noscript,notxpcom] boolean isOnCurrentThreadInfallible();
106  %{C++
107public:
108  %}
109
110  // Fallible version of IsOnCurrentThread.
111  boolean isOnCurrentThread();
112
113  /**
114   * Dispatch an event to this event target.  This function may be called from
115   * any thread, and it may be called re-entrantly.
116   *
117   * @param event
118   *   The alreadyAddRefed<> event to dispatch.
119   *   NOTE that the event will be leaked if it fails to dispatch.
120   * @param flags
121   *   The flags modifying event dispatch.  The flags are described in detail
122   *   below.
123   *
124   * @throws NS_ERROR_INVALID_ARG
125   *   Indicates that event is null.
126   * @throws NS_ERROR_UNEXPECTED
127   *   Indicates that the thread is shutting down and has finished processing
128   * events, so this event would never run and has not been dispatched.
129   */
130  [noscript, binaryname(Dispatch)] void dispatchFromC(in alreadyAddRefed_nsIRunnable event,
131                                                      [default(DISPATCH_NORMAL)] in unsigned long flags);
132  /**
133   * Version of Dispatch to expose to JS, which doesn't require an alreadyAddRefed<>
134   * (it will be converted to that internally)
135   *
136   * @param event
137   *   The (raw) event to dispatch.
138   * @param flags
139   *   The flags modifying event dispatch.  The flags are described in detail
140   *   below.
141   *
142   * @throws NS_ERROR_INVALID_ARG
143   *   Indicates that event is null.
144   * @throws NS_ERROR_UNEXPECTED
145   *   Indicates that the thread is shutting down and has finished processing
146   * events, so this event would never run and has not been dispatched.
147   */
148  [binaryname(DispatchFromScript)] void dispatch(in nsIRunnable event, in unsigned long flags);
149  /**
150   * Dispatch an event to this event target, but do not run it before delay
151   * milliseconds have passed.  This function may be called from any thread.
152   *
153   * @param event
154   *   The alreadyAddrefed<> event to dispatch.
155   * @param delay
156   *   The delay (in ms) before running the event.  If event does not rise to
157   *   the top of the event queue before the delay has passed, it will be set
158   *   aside to execute once the delay has passed.  Otherwise, it will be
159   *   executed immediately.
160   *
161   * @throws NS_ERROR_INVALID_ARG
162   *   Indicates that event is null.
163   * @throws NS_ERROR_UNEXPECTED
164   *   Indicates that the thread is shutting down and has finished processing
165   * events, so this event would never run and has not been dispatched, or
166   * that delay is zero.
167   */
168  [noscript] void delayedDispatch(in alreadyAddRefed_nsIRunnable event, in unsigned long delay);
169};
170
171%{C++
172// convenient aliases:
173#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL
174#define NS_DISPATCH_SYNC   nsIEventTarget::DISPATCH_SYNC
175#define NS_DISPATCH_AT_END nsIEventTarget::DISPATCH_AT_END
176#define NS_DISPATCH_EVENT_MAY_BLOCK nsIEventTarget::DISPATCH_EVENT_MAY_BLOCK
177
178// Convenient NS_DECL variant that includes some C++-only methods.
179#define NS_DECL_NSIEVENTTARGET_FULL                                   \
180    NS_DECL_NSIEVENTTARGET                                            \
181    /* Avoid hiding these methods */                                  \
182    using nsIEventTarget::Dispatch;                                   \
183    using nsIEventTarget::IsOnCurrentThread;
184%}
185