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 (b9b3e10bc8fc)

VCS Links

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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 DDLifetimes_h_
#define DDLifetimes_h_

#include "DDLifetime.h"
#include "DDLoggedTypeTraits.h"
#include "nsClassHashtable.h"
#include "nsTArray.h"

namespace mozilla {

// Managed list of lifetimes.
class DDLifetimes {
 public:
  // DDLifetime for a given aObject, that exists at the aIndex time;
  // otherwise nullptr.
  DDLifetime* FindLifetime(const DDLogObject& aObject,
                           const DDMessageIndex& aIndex);

  // DDLifetime for a given aObject, that exists at the aIndex time;
  // otherwise nullptr.
  const DDLifetime* FindLifetime(const DDLogObject& aObject,
                                 const DDMessageIndex& aIndex) const;

  // Create a lifetime with the given object and construction index&time.
  DDLifetime& CreateLifetime(const DDLogObject& aObject, DDMessageIndex aIndex,
                             const DDTimeStamp& aConstructionTimeStamp);

  // Remove an existing lifetime (assumed to just have been found by
  // FindLifetime()).
  void RemoveLifetime(const DDLifetime* aLifetime);

  // Remove all lifetimes associated with the given HTMLMediaElement.
  void RemoveLifetimesFor(const dom::HTMLMediaElement* aMediaElement);

  // Remove all lifetimes.
  void Clear();

  // Visit all lifetimes associated with an HTMLMediaElement and run
  // `aF(const DDLifetime&)` on each one.
  // If aOnlyHTMLMediaElement is true, only run aF once of that element.
  template <typename F>
  void Visit(const dom::HTMLMediaElement* aMediaElement, F&& aF,
             bool aOnlyHTMLMediaElement = false) const {
    for (auto iter = mLifetimes.ConstIter(); !iter.Done(); iter.Next()) {
      for (const DDLifetime& lifetime : *iter.UserData()) {
        if (lifetime.mMediaElement == aMediaElement) {
          if (aOnlyHTMLMediaElement) {
            if (lifetime.mObject.Pointer() == aMediaElement &&
                lifetime.mObject.TypeName() ==
                    DDLoggedTypeTraits<dom::HTMLMediaElement>::Name()) {
              aF(lifetime);
              break;
            }
            continue;
          }
          static_assert(IsSame<decltype(aF(lifetime)), void>::value, "");
          aF(lifetime);
        }
      }
    }
  }

  // Visit all lifetimes associated with an HTMLMediaElement and run
  // `aF(const DDLifetime&)` on each one.
  // If aF() returns false, the loop continues.
  // If aF() returns true, the loop stops, and true is returned immediately.
  // If all aF() calls have returned false, false is returned at the end.
  template <typename F>
  bool VisitBreakable(const dom::HTMLMediaElement* aMediaElement,
                      F&& aF) const {
    for (auto iter = mLifetimes.ConstIter(); !iter.Done(); iter.Next()) {
      for (const DDLifetime& lifetime : *iter.UserData()) {
        if (lifetime.mMediaElement == aMediaElement) {
          static_assert(IsSame<decltype(aF(lifetime)), bool>::value, "");
          if (aF(lifetime)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;

 private:
  // Hashtable key to use for each DDLogObject.
  class DDLogObjectHashKey : public PLDHashEntryHdr {
   public:
    typedef const DDLogObject& KeyType;
    typedef const DDLogObject* KeyTypePointer;

    explicit DDLogObjectHashKey(KeyTypePointer aKey) : mValue(*aKey) {}
    DDLogObjectHashKey(const DDLogObjectHashKey& aToCopy)
        : mValue(aToCopy.mValue) {}
    ~DDLogObjectHashKey() {}

    KeyType GetKey() const { return mValue; }
    bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }

    static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
    static PLDHashNumber HashKey(KeyTypePointer aKey) {
      return HashBytes(aKey, sizeof(DDLogObject));
    }
    enum { ALLOW_MEMMOVE = true };

   private:
    const DDLogObject mValue;
  };

  // Array of all DDLifetimes for a given DDLogObject; they should be
  // distinguished by their construction&destruction times.
  using LifetimesForObject = nsTArray<DDLifetime>;

  // For each DDLogObject, we store an array of all objects that have used this
  // pointer and type.
  nsClassHashtable<DDLogObjectHashKey, LifetimesForObject> mLifetimes;
};

}  // namespace mozilla

#endif  // DDLifetimes_h_