DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d38398e5144e)

VCS Links

AutoProcessEvent

Dispatcher

ValidatingDispatcher

ValidationType

Macros

Line Code
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
/* -*- 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/. */

#ifndef mozilla_Dispatcher_h
#define mozilla_Dispatcher_h

#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/TaskCategory.h"
#include "nsCOMPtr.h"
#include "nsISupportsImpl.h"

class nsIEventTarget;
class nsIRunnable;

namespace mozilla {
class AbstractThread;
namespace dom {
class TabGroup;
}

// The "main thread" in Gecko will soon be a set of cooperatively scheduled
// "fibers". Global state in Gecko will be partitioned into a series of "groups"
// (with roughly one group per tab). Runnables will be annotated with the set of
// groups that they touch. Two runnables may run concurrently on different
// fibers as long as they touch different groups.
//
// A Dispatcher is an abstract class to represent a "group". Essentially the
// only functionality offered by a Dispatcher is the ability to dispatch
// runnables to the group. TabGroup, DocGroup, and SystemGroup are the concrete
// implementations of Dispatcher.
class Dispatcher
{
public:
  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING

  // Implementations of this method must be safe to call off the main thread.
  virtual nsresult Dispatch(const char* aName,
                            TaskCategory aCategory,
                            already_AddRefed<nsIRunnable>&& aRunnable) = 0;

  // Implementations of this method must be safe to call off the main thread.
  // The returned nsIEventTarget must also be usable from any thread.
  virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const = 0;

  // Must always be called on the main thread. The returned AbstractThread can
  // always be used off the main thread.
  AbstractThread* AbstractMainThreadFor(TaskCategory aCategory);

  // This method performs a safe cast. It returns null if |this| is not of the
  // requested type.
  virtual dom::TabGroup* AsTabGroup() { return nullptr; }

  static nsresult UnlabeledDispatch(const char* aName,
                                    TaskCategory aCategory,
                                    already_AddRefed<nsIRunnable>&& aRunnable);

protected:
  // Implementations are guaranteed that this method is called on the main
  // thread.
  virtual AbstractThread* AbstractMainThreadForImpl(TaskCategory aCategory) = 0;
};

class ValidatingDispatcher : public Dispatcher
{
public:
  ValidatingDispatcher();

  class MOZ_STACK_CLASS AutoProcessEvent final {
  public:
    AutoProcessEvent();
    ~AutoProcessEvent();

  private:
    ValidatingDispatcher* mPrevRunningDispatcher;
  };

  // Ensure that it's valid to access the TabGroup at this time.
  void ValidateAccess() const
  {
    MOZ_ASSERT(!sRunningDispatcher || mAccessValid);
  }

  class Runnable;
  friend class Runnable;

  bool* GetValidAccessPtr() { return &mAccessValid; }

  nsresult Dispatch(const char* aName,
                    TaskCategory aCategory,
                    already_AddRefed<nsIRunnable>&& aRunnable) override;

  nsIEventTarget* EventTargetFor(TaskCategory aCategory) const override;

protected:
  // Implementations are guaranteed that this method is called on the main
  // thread.
  AbstractThread* AbstractMainThreadForImpl(TaskCategory aCategory) override;

  // Helper method to create an event target specific to a particular TaskCategory.
  virtual already_AddRefed<nsIEventTarget>
  CreateEventTargetFor(TaskCategory aCategory);

  // Given an event target returned by |dispatcher->CreateEventTargetFor|, this
  // function returns |dispatcher|.
  static ValidatingDispatcher* FromEventTarget(nsIEventTarget* aEventTarget);

  nsresult LabeledDispatch(const char* aName,
                           TaskCategory aCategory,
                           already_AddRefed<nsIRunnable>&& aRunnable);

  void CreateEventTargets(bool aNeedValidation);
  void Shutdown();

  enum ValidationType {
    StartValidation,
    EndValidation,
  };
  void SetValidatingAccess(ValidationType aType);

  static ValidatingDispatcher* sRunningDispatcher;
  bool mAccessValid;

  nsCOMPtr<nsIEventTarget> mEventTargets[size_t(TaskCategory::Count)];
  RefPtr<AbstractThread> mAbstractThreads[size_t(TaskCategory::Count)];
};

} // namespace mozilla

#endif // mozilla_dom_Dispatcher_h