michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsIThread.idl" michael@0: michael@0: interface nsIRunnable; michael@0: interface nsIThreadObserver; michael@0: michael@0: /** michael@0: * The XPCOM thread object implements this interface, which allows a consumer michael@0: * to observe dispatch activity on the thread. michael@0: */ michael@0: [scriptable, uuid(b24c5af3-43c2-4d17-be14-94d6648a305f)] michael@0: interface nsIThreadInternal : nsIThread michael@0: { michael@0: /** michael@0: * Get/set the current thread observer (may be null). This attribute may be michael@0: * read from any thread, but must only be set on the thread corresponding to michael@0: * this thread object. The observer will be released on the thread michael@0: * corresponding to this thread object after all other events have been michael@0: * processed during a call to Shutdown. michael@0: */ michael@0: attribute nsIThreadObserver observer; michael@0: michael@0: /** michael@0: * The current recursion depth, 0 when no events are running, 1 when a single michael@0: * event is running, and higher when nested events are running. Must only be michael@0: * called on the target thread. michael@0: */ michael@0: readonly attribute unsigned long recursionDepth; michael@0: michael@0: /** michael@0: * Add an observer that will *only* receive onProcessNextEvent, michael@0: * beforeProcessNextEvent. and afterProcessNextEvent callbacks. Always called michael@0: * on the target thread, and the implementation does not have to be michael@0: * threadsafe. Order of callbacks is not guaranteed (i.e. michael@0: * afterProcessNextEvent may be called first depending on whether or not the michael@0: * observer is added in a nested loop). Holds a strong ref. michael@0: */ michael@0: void addObserver(in nsIThreadObserver observer); michael@0: michael@0: /** michael@0: * Remove an observer added via the addObserver call. Once removed the michael@0: * observer will never be called again by the thread. michael@0: */ michael@0: void removeObserver(in nsIThreadObserver observer); michael@0: michael@0: /** michael@0: * This method causes any events currently enqueued on the thread to be michael@0: * suppressed until PopEventQueue is called, and any event dispatched to this michael@0: * thread's nsIEventTarget will queue as well. Calls to PushEventQueue may be michael@0: * nested and must each be paired with a call to PopEventQueue in order to michael@0: * restore the original state of the thread. The returned nsIEventTarget may michael@0: * be used to push events onto the nested queue. Dispatching will be disabled michael@0: * once the event queue is popped. The thread will only ever process pending michael@0: * events for the innermost event queue. Must only be called on the target michael@0: * thread. michael@0: */ michael@0: [noscript] nsIEventTarget pushEventQueue(); michael@0: michael@0: /** michael@0: * Revert a call to PushEventQueue. When an event queue is popped, any events michael@0: * remaining in the queue are appended to the elder queue. This also causes michael@0: * the nsIEventTarget returned from PushEventQueue to stop dispatching events. michael@0: * Must only be called on the target thread, and with the innermost event michael@0: * queue. michael@0: */ michael@0: [noscript] void popEventQueue(in nsIEventTarget aInnermostTarget); michael@0: }; michael@0: michael@0: /** michael@0: * This interface provides the observer with hooks to implement a layered michael@0: * event queue. For example, it is possible to overlay processing events michael@0: * for a GUI toolkit on top of the events for a thread: michael@0: * michael@0: * var NativeQueue; michael@0: * Observer = { michael@0: * onDispatchedEvent(thread) { michael@0: * NativeQueue.signal(); michael@0: * } michael@0: * onProcessNextEvent(thread, mayWait, recursionDepth) { michael@0: * if (NativeQueue.hasNextEvent()) michael@0: * NativeQueue.processNextEvent(); michael@0: * while (mayWait && !thread.hasPendingEvent()) { michael@0: * NativeQueue.wait(); michael@0: * NativeQueue.processNextEvent(); michael@0: * } michael@0: * } michael@0: * }; michael@0: * michael@0: * NOTE: The implementation of this interface must be threadsafe. michael@0: * michael@0: * NOTE: It is valid to change the thread's observer during a call to an michael@0: * observer method. michael@0: * michael@0: * NOTE: Will be split into two interfaces soon: one for onProcessNextEvent and michael@0: * afterProcessNextEvent, then another that inherits the first and adds michael@0: * onDispatchedEvent. michael@0: */ michael@0: [scriptable, uuid(09b424c3-26b0-4128-9039-d66f85b02c63)] michael@0: interface nsIThreadObserver : nsISupports michael@0: { michael@0: /** michael@0: * This method is called after an event has been dispatched to the thread. michael@0: * This method may be called from any thread. michael@0: * michael@0: * @param thread michael@0: * The thread where the event is being dispatched. michael@0: */ michael@0: void onDispatchedEvent(in nsIThreadInternal thread); michael@0: michael@0: /** michael@0: * This method is called when nsIThread::ProcessNextEvent is called. It does michael@0: * not guarantee that an event is actually going to be processed. This method michael@0: * is only called on the target thread. michael@0: * michael@0: * @param thread michael@0: * The thread being asked to process another event. michael@0: * @param mayWait michael@0: * Indicates whether or not the method is allowed to block the calling michael@0: * thread. For example, this parameter is false during thread shutdown. michael@0: * @param recursionDepth michael@0: * Indicates the number of calls to ProcessNextEvent on the call stack in michael@0: * addition to the current call. michael@0: */ michael@0: void onProcessNextEvent(in nsIThreadInternal thread, in boolean mayWait, michael@0: in unsigned long recursionDepth); michael@0: michael@0: /** michael@0: * This method is called (from nsIThread::ProcessNextEvent) after an event michael@0: * is processed. It does not guarantee that an event was actually processed michael@0: * (depends on the value of |eventWasProcessed|. This method is only called michael@0: * on the target thread. michael@0: * michael@0: * @param thread michael@0: * The thread that processed another event. michael@0: * @param recursionDepth michael@0: * Indicates the number of calls to ProcessNextEvent on the call stack in michael@0: * addition to the current call. michael@0: * @param eventWasProcessed michael@0: * Indicates whether an event was actually processed. May be false if the michael@0: * |mayWait| flag was false when calling nsIThread::ProcessNextEvent(). michael@0: */ michael@0: void afterProcessNextEvent(in nsIThreadInternal thread, michael@0: in unsigned long recursionDepth, michael@0: in bool eventWasProcessed); michael@0: };