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 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
|
/* -*- 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"
#include "mozilla/TypedEnumBits.h"
class nsITargetShutdownTask;
%}
native alreadyAddRefed_nsIRunnable(already_AddRefed<nsIRunnable>);
[ptr] native nsITargetShutdownTask(nsITargetShutdownTask);
[builtinclass, scriptable, rust_sync, uuid(a03b8b63-af8b-4164-b0e5-c41e8b2b7cfa)]
interface nsIEventTarget : nsISupports
{
/**
* Flags used to customize the behaviour of a `Dispatch` call.
*
* WARNING: These flags are generally hints, and are not universally supported
* by all nsIEventTarget implementations. An implementation may ignore some or
* all of these flags.
*
* HISTORIC NOTE: There used to be a `DISPATCH_SYNC` flag which would spin a
* nested event loop while dispatching (and could not be safely ignored by
* event target implementations), but this has since been removed.
*/
cenum DispatchFlags : 32 {
/**
* DISPATCH_NORMAL corresponds to the absense of other flags. This is used
* for dispatching async events to an event target which will be queued for
* later processing.
*/
DISPATCH_NORMAL = 0,
// NOTE: 1 << 0 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.
*/
DISPATCH_AT_END = 1 << 1,
/**
* 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.
*/
DISPATCH_EVENT_MAY_BLOCK = 1 << 2,
/**
* 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.
*/
DISPATCH_IGNORE_BLOCK_DISPATCH = 1 << 3,
/**
* This flag specifies that the caller of the given dispatch is prepared to
* handle dispatch failures itself.
*
* Some nsIEventTarget implementations, such as nsThread, leak the passed-in
* runnable if there is a failure when dispatching (e.g. due to the thread
* being destroyed). This is done as many callers are unprepared to handle
* calls to Dispatch failing, and could otherwise e.g. destroy a object on
* the wrong thread.
*
* By specifying DISPATCH_FALLIBLE, you communicate to the nsIEventTarget
* implementation that you are prepared to handle the consequences of the
* dispatch failing. nsIEventTarget implementations should neither leak
* passed-in runnables nor fire assertions on state-related error codepaths
* (such as late shutdown dispatch assertions) when DISPATCH_FALLIBLE is
* specified.
*
* When using DISPATCH_FALLIBLE, the caller must be careful that the event
* object is safe to discard on the calling thread, and that other systems
* do not depend on the runnable completing on error cases.
*
* NOTE: Many nsIEventTarget implementations (including TaskQueue and
* nsThreadPool) never leak the passed-in runnable on failure, whether or
* not this flag is specified. Dispatched events may always be released by
* the dispatcher on error for those types.
*
* See bug 803174, bug 1237213 and bug 1824189 for historical context.
*/
DISPATCH_FALLIBLE = 1 << 4,
};
/**
* 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();
/* until we can get rid of all uses, keep the non-alreadyAddRefed<> version */
%{C++
nsresult Dispatch(nsIRunnable* aEvent, DispatchFlags aFlags) {
return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
}
%}
/**
* 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 should be leaked if it fails to dispatch unless
* NS_DISPATCH_FALLIBLE is passed.
* @param flags
* The flags modifying event dispatch. The flags are described in detail
* above.
*
* @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 nsIEventTarget_DispatchFlags 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
* above.
*
* @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 nsIEventTarget_DispatchFlags 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
#define NS_DISPATCH_FALLIBLE nsIEventTarget::DISPATCH_FALLIBLE
// Convenience bitwise operators for the flag cenum
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsIEventTarget::DispatchFlags)
// 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;
%}
|