Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/threads/ThrottledEventQueue.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
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
// nsIEventTarget wrapper for throttling event dispatch.
8
9
#ifndef mozilla_ThrottledEventQueue_h
10
#define mozilla_ThrottledEventQueue_h
11
12
#include "nsISerialEventTarget.h"
13
14
#define NS_THROTTLEDEVENTQUEUE_IID \
15
{ 0x8f3cf7dc, 0xfc14, 0x4ad5, \
16
  { 0x9f, 0xd5, 0xdb, 0x79, 0xbc, 0xe6, 0xd5, 0x08 } }
17
18
namespace mozilla {
19
20
// A ThrottledEventQueue is an event target that can be used to throttle
21
// events being dispatched to another base target.  It maintains its
22
// own queue of events and only dispatches one at a time to the wrapped
23
// target.  This can be used to avoid flooding the base target.
24
//
25
// Flooding is avoided via a very simply principal.  Runnables dispatched
26
// to the ThrottledEventQueue are only dispatched to the base target
27
// one at a time.  Only once that runnable has executed will we dispatch
28
// the next runnable to the base target.  This in effect makes all
29
// runnables passing through the ThrottledEventQueue yield to other work
30
// on the base target.
31
//
32
// ThrottledEventQueue keeps runnables waiting to be dispatched to the
33
// base in its own internal queue.  Code can query the length of this
34
// queue using IsEmpty() and Length().  Further, code implement back
35
// pressure by checking the depth of the queue and deciding to stop
36
// issuing runnables if they see the ThrottledEventQueue is backed up.
37
// Code running on other threads could even use AwaitIdle() to block
38
// all operation until the ThrottledEventQueue drains.
39
//
40
// Note, this class is similar to TaskQueue, but also differs in a few
41
// ways.  First, it is a very simple nsIEventTarget implementation.  It
42
// does not use the AbstractThread API.
43
//
44
// In addition, ThrottledEventQueue currently dispatches its next
45
// runnable to the base target *before* running the current event.  This
46
// allows the event code to spin the event loop without stalling the
47
// ThrottledEventQueue.  In contrast, TaskQueue only dispatches its next
48
// runnable after running the current event.  That approach is necessary
49
// for TaskQueue in order to work with thread pool targets.
50
//
51
// So, if you are targeting a thread pool you probably want a TaskQueue.
52
// If you are targeting a single thread or other non-concurrent event
53
// target, you probably want a ThrottledEventQueue.
54
//
55
// If you drop a ThrottledEventQueue while its queue still has events to be run,
56
// they will continue to be dispatched as usual to the base. Only once the last
57
// event has run will all the ThrottledEventQueue's memory be freed.
58
class ThrottledEventQueue final : public nsISerialEventTarget
59
{
60
  class Inner;
61
  RefPtr<Inner> mInner;
62
63
  explicit ThrottledEventQueue(already_AddRefed<Inner> aInner);
64
0
  ~ThrottledEventQueue() = default;
65
66
public:
67
  // Attempt to create a ThrottledEventQueue for the given target.  This
68
  // may return nullptr if the browser is already shutting down.
69
  static already_AddRefed<ThrottledEventQueue>
70
  Create(nsISerialEventTarget* aBaseTarget);
71
72
  // Determine if there are any events pending in the queue.
73
  bool IsEmpty() const;
74
75
  // Determine how many events are pending in the queue.
76
  uint32_t Length() const;
77
78
  // Block the current thread until the queue is empty.  This may not
79
  // be called on the main thread or the base target.
80
  void AwaitIdle() const;
81
82
  NS_DECL_THREADSAFE_ISUPPORTS
83
  NS_DECL_NSIEVENTTARGET_FULL
84
85
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_THROTTLEDEVENTQUEUE_IID);
86
};
87
88
NS_DEFINE_STATIC_IID_ACCESSOR(ThrottledEventQueue, NS_THROTTLEDEVENTQUEUE_IID);
89
90
} // namespace mozilla
91
92
#endif // mozilla_ThrottledEventQueue_h