Global Metrics

path: .metrics.halstead.volume
old: 10110.524624064596
new: 5723.632360468999

path: .metrics.halstead.purity_ratio
old: 1.246142017060739
new: 1.4247571855639705

path: .metrics.halstead.n2
old: 191.0
new: 137.0

path: .metrics.halstead.estimated_program_length
old: 1613.753912093657
new: 1107.036333183205

path: .metrics.halstead.length
old: 1295.0
new: 777.0

path: .metrics.halstead.level
old: 0.018700739217702066
new: 0.030109890109890108

path: .metrics.halstead.n1
old: 33.0
new: 28.0

path: .metrics.halstead.time
old: 30036.02188710988
new: 10560.635539389272

path: .metrics.halstead.effort
old: 540648.3939679778
new: 190091.4397090069

path: .metrics.halstead.difficulty
old: 53.473821989528794
new: 33.21167883211679

path: .metrics.halstead.N2
old: 619.0
new: 325.0

path: .metrics.halstead.bugs
old: 2.212187955499246
new: 1.1020140171091266

path: .metrics.halstead.N1
old: 676.0
new: 452.0

path: .metrics.halstead.vocabulary
old: 224.0
new: 165.0

path: .metrics.cyclomatic.sum
old: 46.0
new: 40.0

path: .metrics.cyclomatic.average
old: 2.090909090909091
new: 1.6

path: .metrics.nexits.sum
old: 16.0
new: 7.0

path: .metrics.nexits.average
old: 0.9411764705882352
new: 0.4375

path: .metrics.mi.mi_sei
old: -27.208696669149298
new: -10.88946763748392

path: .metrics.mi.mi_visual_studio
old: 7.12629413648554
new: 14.72553586440203

path: .metrics.mi.mi_original
old: 12.185962973390277
new: 25.180666328127472

path: .metrics.nom.functions
old: 17.0
new: 16.0

path: .metrics.nom.total
old: 17.0
new: 16.0

path: .metrics.nargs.sum
old: 55.0
new: 5.0

path: .metrics.nargs.average
old: 3.235294117647059
new: 0.3125

path: .metrics.cognitive.average
old: 1.8823529411764703
new: 0.6875

path: .metrics.cognitive.sum
old: 32.0
new: 11.0

path: .metrics.loc.ploc
old: 373.0
new: 194.0

path: .metrics.loc.sloc
old: 488.0
new: 286.0

path: .metrics.loc.cloc
old: 62.0
new: 31.0

path: .metrics.loc.lloc
old: 87.0
new: 48.0

path: .metrics.loc.blank
old: 53.0
new: 61.0

Spaces Data

Minimal test - lines (44, 226)

path: .spaces[3].metrics.nom.total
old: 1.0
new: 12.0

path: .spaces[3].metrics.nom.functions
old: 1.0
new: 12.0

path: .spaces[3].metrics.nargs.average
old: 3.0
new: 0.16666666666666666

path: .spaces[3].metrics.nargs.sum
old: 3.0
new: 2.0

path: .spaces[3].metrics.cyclomatic.average
old: 3.0
new: 1.8571428571428572

path: .spaces[3].metrics.cyclomatic.sum
old: 3.0
new: 26.0

path: .spaces[3].metrics.mi.mi_original
old: 86.97710700312962
new: 37.226564323703755

path: .spaces[3].metrics.mi.mi_sei
old: 50.08604853048445
new: 2.764327780374341

path: .spaces[3].metrics.mi.mi_visual_studio
old: 50.86380526498808
new: 21.769920657136694

path: .spaces[3].metrics.halstead.difficulty
old: 16.0
new: 30.796116504854368

path: .spaces[3].metrics.halstead.n1
old: 12.0
new: 26.0

path: .spaces[3].metrics.halstead.estimated_program_length
old: 153.0586500259616
new: 810.9209869715398

path: .spaces[3].metrics.halstead.N1
old: 70.0
new: 357.0

path: .spaces[3].metrics.halstead.n2
old: 24.0
new: 103.0

path: .spaces[3].metrics.halstead.time
old: 615.7955112829064
new: 7209.281189523052

path: .spaces[3].metrics.halstead.vocabulary
old: 36.0
new: 129.0

path: .spaces[3].metrics.halstead.purity_ratio
old: 1.142228731537027
new: 1.34928616800589

path: .spaces[3].metrics.halstead.volume
old: 692.7699501932698
new: 4213.747580509375

path: .spaces[3].metrics.halstead.N2
old: 64.0
new: 244.0

path: .spaces[3].metrics.halstead.effort
old: 11084.319203092316
new: 129767.06141141494

path: .spaces[3].metrics.halstead.bugs
old: 0.16571103427117215
new: 0.8543878400223639

path: .spaces[3].metrics.halstead.level
old: 0.0625
new: 0.032471626733921816

path: .spaces[3].metrics.halstead.length
old: 134.0
new: 601.0

path: .spaces[3].metrics.nexits.sum
old: 0.0
new: 6.0

path: .spaces[3].metrics.nexits.average
old: 0.0
new: 0.5

path: .spaces[3].metrics.loc.sloc
old: 21.0
new: 183.0

path: .spaces[3].metrics.loc.ploc
old: 21.0
new: 132.0

path: .spaces[3].metrics.loc.cloc
old: 0.0
new: 16.0

path: .spaces[3].metrics.loc.blank
old: 0.0
new: 35.0

path: .spaces[3].metrics.loc.lloc
old: 14.0
new: 39.0

path: .spaces[3].metrics.cognitive.average
old: 3.0
new: 0.6666666666666666

path: .spaces[3].metrics.cognitive.sum
old: 3.0
new: 8.0

Code

class nsTimerImpl {
  ~nsTimerImpl() { MOZ_ASSERT(!mHolder); }

 public:
  typedef mozilla::TimeStamp TimeStamp;

  nsTimerImpl(nsITimer* aTimer, nsIEventTarget* aTarget);
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsTimerImpl)
  NS_DECL_NON_VIRTUAL_NSITIMER

  static nsresult Startup();
  static void Shutdown();

  void SetDelayInternal(uint32_t aDelay, TimeStamp aBase = TimeStamp::Now());
  void CancelImpl(bool aClearITimer);

  void Fire(int32_t aGeneration);

#ifdef MOZ_TASK_TRACER
  void GetTLSTraceInfo();
  mozilla::tasktracer::TracedTaskCommon GetTracedTask();
#endif

  int32_t GetGeneration() { return mGeneration; }

  struct Callback {
    Callback() : mType(Type::Unknown), mName(Nothing), mClosure(nullptr) {
      mCallback.c = nullptr;
    }

    Callback(const Callback& other) : Callback() { *this = other; }

    enum class Type : uint8_t {
      Unknown = 0,
      Interface = 1,
      Function = 2,
      Observer = 3,
    };

    Callback& operator=(const Callback& other) {
      if (this != &other) {
        clear();
        mType = other.mType;
        switch (mType) {
          case Type::Unknown:
            break;
          case Type::Interface:
            mCallback.i = other.mCallback.i;
            NS_ADDREF(mCallback.i);
            break;
          case Type::Function:
            mCallback.c = other.mCallback.c;
            break;
          case Type::Observer:
            mCallback.o = other.mCallback.o;
            NS_ADDREF(mCallback.o);
            break;
        }
        mName = other.mName;
        mClosure = other.mClosure;
      }
      return *this;
    }

    ~Callback() { clear(); }

    void clear() {
      if (mType == Type::Interface) {
        NS_RELEASE(mCallback.i);
      } else if (mType == Type::Observer) {
        NS_RELEASE(mCallback.o);
      }
      mType = Type::Unknown;
    }

    void swap(Callback& other) {
      std::swap(mType, other.mType);
      std::swap(mCallback, other.mCallback);
      std::swap(mName, other.mName);
      std::swap(mClosure, other.mClosure);
    }

    Type mType;

    union CallbackUnion {
      nsTimerCallbackFunc c;
      // These refcounted references are managed manually, as they are in a
      // union
      nsITimerCallback* MOZ_OWNING_REF i;
      nsIObserver* MOZ_OWNING_REF o;
    } mCallback;

    // |Name| is a tagged union type representing one of (a) nothing, (b) a
    // string, or (c) a function. mozilla::Variant doesn't naturally handle the
    // "nothing" case, so we define a dummy type and value (which is unused and
    // so the exact value doesn't matter) for it.
    typedef const int NameNothing;
    typedef const char* NameString;
    typedef nsTimerNameCallbackFunc NameFunc;
    typedef mozilla::Variant Name;
    static const NameNothing Nothing;
    Name mName;

    void* mClosure;
  };

  nsresult InitCommon(uint32_t aDelayMS, uint32_t aType,
                      Callback&& newCallback);

  nsresult InitCommon(const mozilla::TimeDuration& aDelay, uint32_t aType,
                      Callback&& newCallback);

  Callback& GetCallback() {
    mMutex.AssertCurrentThreadOwns();
    return mCallback;
  }

  bool IsRepeating() const {
    static_assert(nsITimer::TYPE_ONE_SHOT < nsITimer::TYPE_REPEATING_SLACK,
                  "invalid ordering of timer types!");
    static_assert(
        nsITimer::TYPE_REPEATING_SLACK < nsITimer::TYPE_REPEATING_PRECISE,
        "invalid ordering of timer types!");
    static_assert(nsITimer::TYPE_REPEATING_PRECISE <
                      nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP,
                  "invalid ordering of timer types!");
    return mType >= nsITimer::TYPE_REPEATING_SLACK &&
           mType < nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY;
  }

  bool IsLowPriority() const {
    return mType == nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY ||
           mType == nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY;
  }

  bool IsSlack() const {
    return mType == nsITimer::TYPE_REPEATING_SLACK ||
           mType == nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY;
  }

  void GetName(nsACString& aName);

  void SetHolder(nsTimerImplHolder* aHolder);

  nsCOMPtr mEventTarget;

  void LogFiring(const Callback& aCallback, uint8_t aType, uint32_t aDelay);

  nsresult InitWithFuncCallbackCommon(nsTimerCallbackFunc aFunc, void* aClosure,
                                      uint32_t aDelay, uint32_t aType,
                                      const Callback::Name& aName);

  // This weak reference must be cleared by the nsTimerImplHolder by calling
  // SetHolder(nullptr) before the holder is destroyed.
  nsTimerImplHolder* mHolder;

  // These members are set by the initiating thread, when the timer's type is
  // changed and during the period where it fires on that thread.
  uint8_t mType;

  // The generation number of this timer, re-generated each time the timer is
  // initialized so one-shot timers can be canceled and re-initialized by the
  // arming thread without any bad race conditions.
  // Updated only after this timer has been removed from the timer thread.
  int32_t mGeneration;

  mozilla::TimeDuration mDelay;
  // Updated only after this timer has been removed from the timer thread.
  mozilla::TimeStamp mTimeout;

#ifdef MOZ_TASK_TRACER
  mozilla::tasktracer::TracedTaskCommon mTracedTask;
#endif

  static double sDeltaSum;
  static double sDeltaSumSquared;
  static double sDeltaNum;
  RefPtr mITimer;
  mozilla::Mutex mMutex;
  Callback mCallback;
  // Counter because in rare cases we can Fire reentrantly
  unsigned int mFiring;
};

Minimal test - lines (37, 39)

path: .spaces[2].metrics.cognitive.average
old: 0.0
new: null

path: .spaces[2].metrics.nom.total
old: 1.0
new: 0.0

path: .spaces[2].metrics.nom.functions
old: 1.0
new: 0.0

path: .spaces[2].metrics.halstead.n2
old: 9.0
new: 2.0

path: .spaces[2].metrics.halstead.n1
old: 9.0
new: 2.0

path: .spaces[2].metrics.halstead.estimated_program_length
old: 57.05865002596162
new: 4.0

path: .spaces[2].metrics.halstead.purity_ratio
old: 2.282346001038465
new: 1.0

path: .spaces[2].metrics.halstead.vocabulary
old: 18.0
new: 4.0

path: .spaces[2].metrics.halstead.volume
old: 104.2481250360578
new: 8.0

path: .spaces[2].metrics.halstead.time
old: 31.85359376101766
new: 0.4444444444444444

path: .spaces[2].metrics.halstead.bugs
old: 0.02300555456638979
new: 0.0013333333333333333

path: .spaces[2].metrics.halstead.N1
old: 14.0
new: 2.0

path: .spaces[2].metrics.halstead.N2
old: 11.0
new: 2.0

path: .spaces[2].metrics.halstead.effort
old: 573.3646876983179
new: 8.0

path: .spaces[2].metrics.halstead.level
old: 0.18181818181818185
new: 1.0

path: .spaces[2].metrics.halstead.length
old: 25.0
new: 4.0

path: .spaces[2].metrics.halstead.difficulty
old: 5.5
new: 1.0

path: .spaces[2].metrics.mi.mi_original
old: 117.5802724471975
new: 141.92938490684145

path: .spaces[2].metrics.mi.mi_sei
old: 133.02597635258363
new: 129.26360748831726

path: .spaces[2].metrics.mi.mi_visual_studio
old: 68.76039324397514
new: 82.99964029639851

path: .spaces[2].metrics.nexits.average
old: 1.0
new: null

path: .spaces[2].metrics.nexits.sum
old: 1.0
new: 0.0

path: .spaces[2].metrics.nargs.sum
old: 1.0
new: 0.0

path: .spaces[2].metrics.nargs.average
old: 1.0
new: null

path: .spaces[2].metrics.cyclomatic.sum
old: 1.0
new: 2.0

path: .spaces[2].metrics.loc.lloc
old: 1.0
new: 0.0

path: .spaces[2].metrics.loc.sloc
old: 6.0
new: 3.0

path: .spaces[2].metrics.loc.ploc
old: 4.0
new: 3.0

path: .spaces[2].metrics.loc.cloc
old: 2.0
new: 0.0

Code

namespace mozilla {
class LogModule;
}

Minimal test - lines (35, 35)

path: .spaces[1].metrics.halstead.N2
old: 6.0
new: 1.0

path: .spaces[1].metrics.halstead.n2
old: 6.0
new: 1.0

path: .spaces[1].metrics.halstead.vocabulary
old: 9.0
new: 1.0

path: .spaces[1].metrics.halstead.length
old: 14.0
new: 1.0

path: .spaces[1].metrics.halstead.difficulty
old: 1.5
new: 0.0

path: .spaces[1].metrics.halstead.effort
old: 66.56842503028855
new: 0.0

path: .spaces[1].metrics.halstead.estimated_program_length
old: 20.264662506490403
new: null

path: .spaces[1].metrics.halstead.volume
old: 44.37895002019237
new: 0.0

path: .spaces[1].metrics.halstead.bugs
old: 0.005475085848401926
new: 0.0

path: .spaces[1].metrics.halstead.n1
old: 3.0
new: 0.0

path: .spaces[1].metrics.halstead.level
old: 0.6666666666666666
new: null

path: .spaces[1].metrics.halstead.N1
old: 8.0
new: 0.0

path: .spaces[1].metrics.halstead.time
old: 3.6982458350160305
new: 0.0

path: .spaces[1].metrics.halstead.purity_ratio
old: 1.447475893320743
new: null

path: .spaces[1].metrics.mi.mi_sei
old: 129.99658447562217
new: null

path: .spaces[1].metrics.mi.mi_visual_studio
old: 71.35737851167426
new: null

path: .spaces[1].metrics.mi.mi_original
old: 122.02111725496296
new: null

path: .spaces[1].metrics.loc.sloc
old: 6.0
new: 1.0

path: .spaces[1].metrics.loc.cloc
old: 1.0
new: 0.0

path: .spaces[1].metrics.loc.ploc
old: 6.0
new: 1.0

Code

class nsTimerImplHolder;

Minimal test - lines (34, 34)

path: .spaces[0].metrics.loc.blank
old: 3.0
new: 0.0

path: .spaces[0].metrics.loc.cloc
old: 2.0
new: 0.0

path: .spaces[0].metrics.loc.ploc
old: 7.0
new: 1.0

path: .spaces[0].metrics.loc.sloc
old: 12.0
new: 1.0

path: .spaces[0].metrics.mi.mi_original
old: 109.32806050611424
new: null

path: .spaces[0].metrics.mi.mi_sei
old: 111.68437445033597
new: null

path: .spaces[0].metrics.mi.mi_visual_studio
old: 63.93453830766914
new: null

path: .spaces[0].metrics.halstead.n2
old: 7.0
new: 1.0

path: .spaces[0].metrics.halstead.N1
old: 10.0
new: 0.0

path: .spaces[0].metrics.halstead.estimated_program_length
old: 27.651484454403228
new: null

path: .spaces[0].metrics.halstead.level
old: 0.5
new: null

path: .spaces[0].metrics.halstead.n1
old: 4.0
new: 0.0

path: .spaces[0].metrics.halstead.difficulty
old: 2.0
new: 0.0

path: .spaces[0].metrics.halstead.length
old: 17.0
new: 1.0

path: .spaces[0].metrics.halstead.effort
old: 117.6206750336681
new: 0.0

path: .spaces[0].metrics.halstead.volume
old: 58.81033751683405
new: 0.0

path: .spaces[0].metrics.halstead.time
old: 6.534481946314894
new: 0.0

path: .spaces[0].metrics.halstead.purity_ratio
old: 1.6265579090825428
new: null

path: .spaces[0].metrics.halstead.bugs
old: 0.008002048702810353
new: 0.0

path: .spaces[0].metrics.halstead.N2
old: 7.0
new: 1.0

path: .spaces[0].metrics.halstead.vocabulary
old: 11.0
new: 1.0

Code

class nsIObserver;

Minimal test - lines (228, 255)

path: .spaces[4].metrics.halstead.volume
old: 104.2481250360578
new: 361.20986172877406

path: .spaces[4].metrics.halstead.N2
old: 12.0
new: 32.0

path: .spaces[4].metrics.halstead.n1
old: 9.0
new: 12.0

path: .spaces[4].metrics.halstead.difficulty
old: 6.0
new: 8.727272727272727

path: .spaces[4].metrics.halstead.length
old: 25.0
new: 71.0

path: .spaces[4].metrics.halstead.vocabulary
old: 18.0
new: 34.0

path: .spaces[4].metrics.halstead.N1
old: 13.0
new: 39.0

path: .spaces[4].metrics.halstead.purity_ratio
old: 2.282346001038465
new: 1.9877048678686535

path: .spaces[4].metrics.halstead.level
old: 0.16666666666666666
new: 0.11458333333333334

path: .spaces[4].metrics.halstead.estimated_program_length
old: 57.05865002596162
new: 141.1270456186744

path: .spaces[4].metrics.halstead.bugs
old: 0.024379516068267628
new: 0.07166451671469155

path: .spaces[4].metrics.halstead.effort
old: 625.4887502163468
new: 3152.3769750874826

path: .spaces[4].metrics.halstead.time
old: 34.74937501201927
new: 175.13205417152682

path: .spaces[4].metrics.halstead.n2
old: 9.0
new: 22.0

path: .spaces[4].metrics.mi.mi_visual_studio
old: 70.48765009781262
new: 50.25327455621647

path: .spaces[4].metrics.mi.mi_sei
old: 98.29460120784424
new: 76.11052135095986

path: .spaces[4].metrics.mi.mi_original
old: 120.53388166725958
new: 85.93309949113016

path: .spaces[4].metrics.cyclomatic.sum
old: 1.0
new: 2.0

path: .spaces[4].metrics.nexits.average
old: 1.0
new: 0.0

path: .spaces[4].metrics.nexits.sum
old: 1.0
new: 0.0

path: .spaces[4].metrics.loc.blank
old: 0.0
new: 7.0

path: .spaces[4].metrics.loc.ploc
old: 5.0
new: 17.0

path: .spaces[4].metrics.loc.cloc
old: 0.0
new: 4.0

path: .spaces[4].metrics.loc.lloc
old: 1.0
new: 0.0

path: .spaces[4].metrics.loc.sloc
old: 5.0
new: 28.0

path: .spaces[4].metrics.nargs.average
old: 2.0
new: 1.0

path: .spaces[4].metrics.nargs.sum
old: 2.0
new: 1.0

Code

class nsTimer final : public nsITimer {
  explicit nsTimer(nsIEventTarget* aTarget)
      : mImpl(new nsTimerImpl(this, aTarget)) {}

  virtual ~nsTimer();

 public:
  friend class TimerThread;
  friend class nsTimerEvent;

  NS_DECL_THREADSAFE_ISUPPORTS
  NS_FORWARD_SAFE_NSITIMER(mImpl);

  virtual size_t SizeOfIncludingThis(
      mozilla::MallocSizeOf aMallocSizeOf) const override;

  // Create a timer targeting the given target.  nullptr indicates that the
  // current thread should be used as the timer's target.
  static RefPtr WithEventTarget(nsIEventTarget* aTarget);

  static nsresult XPCOMConstructor(nsISupports* aOuter, REFNSIID aIID,
                                   void** aResult);

 private:
  // nsTimerImpl holds a strong ref to us. When our refcount goes to 1, we will
  // null this to break the cycle.
  RefPtr mImpl;
};

Minimal test - lines (259, 284)

path: .spaces[5].metrics.cognitive.sum
old: 0.0
new: 3.0

path: .spaces[5].metrics.cognitive.average
old: 0.0
new: 1.0

path: .spaces[5].metrics.nargs.average
old: 1.0
new: 0.6666666666666666

path: .spaces[5].metrics.nargs.sum
old: 1.0
new: 2.0

path: .spaces[5].metrics.nexits.average
old: 1.0
new: 0.3333333333333333

path: .spaces[5].metrics.loc.lloc
old: 1.0
new: 9.0

path: .spaces[5].metrics.loc.ploc
old: 5.0
new: 23.0

path: .spaces[5].metrics.loc.sloc
old: 5.0
new: 26.0

path: .spaces[5].metrics.loc.blank
old: 0.0
new: 3.0

path: .spaces[5].metrics.mi.mi_visual_studio
old: 71.76322352505298
new: 50.39360432282213

path: .spaces[5].metrics.mi.mi_original
old: 122.7151122278406
new: 86.17306339202582

path: .spaces[5].metrics.mi.mi_sei
old: 101.44145172062991
new: 49.33333823770444

path: .spaces[5].metrics.nom.functions
old: 1.0
new: 3.0

path: .spaces[5].metrics.nom.total
old: 1.0
new: 3.0

path: .spaces[5].metrics.cyclomatic.sum
old: 1.0
new: 7.0

path: .spaces[5].metrics.cyclomatic.average
old: 1.0
new: 1.75

path: .spaces[5].metrics.halstead.N2
old: 9.0
new: 30.0

path: .spaces[5].metrics.halstead.n2
old: 7.0
new: 10.0

path: .spaces[5].metrics.halstead.n1
old: 7.0
new: 15.0

path: .spaces[5].metrics.halstead.vocabulary
old: 14.0
new: 25.0

path: .spaces[5].metrics.halstead.purity_ratio
old: 2.1834982727114696
new: 1.2243018651066857

path: .spaces[5].metrics.halstead.bugs
old: 0.01521543361852368
new: 0.131510503656422

path: .spaces[5].metrics.halstead.level
old: 0.2222222222222222
new: 0.044444444444444446

path: .spaces[5].metrics.halstead.difficulty
old: 4.5
new: 22.5

path: .spaces[5].metrics.halstead.time
old: 17.133097149259218
new: 435.3615177913804

path: .spaces[5].metrics.halstead.volume
old: 68.53238859703687
new: 348.2892142331043

path: .spaces[5].metrics.halstead.effort
old: 308.3957486866659
new: 7836.507320244847

path: .spaces[5].metrics.halstead.N1
old: 9.0
new: 45.0

path: .spaces[5].metrics.halstead.length
old: 18.0
new: 75.0

path: .spaces[5].metrics.halstead.estimated_program_length
old: 39.302968908806456
new: 91.8226398830014

Code

class nsTimerImplHolder {
 public:
  explicit nsTimerImplHolder(nsTimerImpl* aTimerImpl) : mTimerImpl(aTimerImpl) {
    if (mTimerImpl) {
      mTimerImpl->SetHolder(this);
    }
  }

  ~nsTimerImplHolder() {
    if (mTimerImpl) {
      mTimerImpl->SetHolder(nullptr);
    }
  }

  void Forget(nsTimerImpl* aTimerImpl) {
    if (MOZ_UNLIKELY(!mTimerImpl)) {
      return;
    }
    MOZ_ASSERT(aTimerImpl == mTimerImpl);
    mTimerImpl->SetHolder(nullptr);
    mTimerImpl = nullptr;
  }

 protected:
  RefPtr mTimerImpl;
};