/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
// nsIEventTarget wrapper for throttling event dispatch.
// A ThrottledEventQueue is an event target that can be used to throttle // events being dispatched to another base target. It maintains its // own queue of events and only dispatches one at a time to the wrapped // target. This can be used to avoid flooding the base target. // // Flooding is avoided via a very simple principle. Runnables dispatched // to the ThrottledEventQueue are only dispatched to the base target // one at a time. Only once that runnable has executed will we dispatch // the next runnable to the base target. This in effect makes all // runnables passing through the ThrottledEventQueue yield to other work // on the base target. // // ThrottledEventQueue keeps runnables waiting to be dispatched to the // base in its own internal queue. Code can query the length of this // queue using IsEmpty() and Length(). Further, code implement back // pressure by checking the depth of the queue and deciding to stop // issuing runnables if they see the ThrottledEventQueue is backed up. // Code running on other threads could even use AwaitIdle() to block // all operation until the ThrottledEventQueue drains. // // Note, this class is similar to TaskQueue, but also differs in a few // ways. First, it is a very simple nsIEventTarget implementation. It // does not use the AbstractThread API. // // In addition, ThrottledEventQueue currently dispatches its next // runnable to the base target *before* running the current event. This // allows the event code to spin the event loop without stalling the // ThrottledEventQueue. In contrast, TaskQueue only dispatches its next // runnable after running the current event. That approach is necessary // for TaskQueue in order to work with thread pool targets. // // So, if you are targeting a thread pool you probably want a TaskQueue. // If you are targeting a single thread or other non-concurrent event // target, you probably want a ThrottledEventQueue. // // If you drop a ThrottledEventQueue while its queue still has events to be run, // they will continue to be dispatched as usual to the base. Only once the last // event has run will all the ThrottledEventQueue's memory be freed. class ThrottledEventQueue final : public nsISerialEventTarget { class Inner;
RefPtr<Inner> mInner;
public: // Create a ThrottledEventQueue for the given target. static already_AddRefed<ThrottledEventQueue> Create(
nsISerialEventTarget* aBaseTarget, constchar* aName,
uint32_t aPriority = nsIRunnablePriority::PRIORITY_NORMAL);
// Determine if there are any events pending in the queue. bool IsEmpty() const;
// Determine how many events are pending in the queue.
uint32_t Length() const;
already_AddRefed<nsIRunnable> GetEvent();
// Block the current thread until the queue is empty. This may not be called // on the main thread or the base target. The ThrottledEventQueue must not be // paused. void AwaitIdle() const;
// If |aIsPaused| is true, pause execution of events from this queue. No // events from this queue will be run until this is called with |aIsPaused| // false. // // To un-pause a ThrottledEventQueue, we need to dispatch a runnable to the // underlying event target. That operation may fail, so this method is // fallible as well. // // Note that, although ThrottledEventQueue's behavior is descibed as queueing // events on the base target, an event queued on a TEQ is never actually moved // to any other queue. What is actually dispatched to the base is an // "executor" event which, when run, removes an event from the TEQ and runs it // immediately. This means that you can pause a TEQ even after the executor // has been queued on the base target, and even so, no events from the TEQ // will run. When the base target gets around to running the executor, the // executor will see that the TEQ is paused, and do nothing.
[[nodiscard]] nsresult SetIsPaused(bool aIsPaused);
// Return true if this ThrottledEventQueue is paused. bool IsPaused() const;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.