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 (27a812186ff4)

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 129 130 131
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_imagelib_DiscardTracker_h_
#define mozilla_imagelib_DiscardTracker_h_

#include "mozilla/Atomics.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "prlock.h"
#include "nsThreadUtils.h"
#include "nsAutoPtr.h"

class nsITimer;

namespace mozilla {
namespace image {

class RasterImage;

/**
 * This static class maintains a linked list of RasterImage objects which are
 * eligible for discarding.
 *
 * When Reset() is called, the node is removed from its position in the list
 * (if it was there before) and appended to the beginnings of the list.
 *
 * Periodically (on a timer and when we notice that we're using more memory
 * than we'd like for decoded images), we go through the list and discard
 * decoded data from images at the end of the list.
 */
class DiscardTracker
{
  public:
    /**
     * The DiscardTracker keeps a linked list of Node objects.  Each object
     * points to a RasterImage and contains a timestamp indicating when the
     * node was inserted into the tracker.
     *
     * This structure is embedded within each RasterImage object, and we do
     * |mDiscardTrackerNode.img = this| on RasterImage construction.  Thus, a
     * RasterImage must always call DiscardTracker::Remove() in its destructor
     * to avoid having the tracker point to bogus memory.
     */
    struct Node : public LinkedListElement<Node>
    {
      RasterImage *img;
      TimeStamp timestamp;
    };

    /**
     * Add an image to the front of the tracker's list, or move it to the front
     * if it's already in the list.  This function is main thread only.
     */
    static nsresult Reset(struct Node* node);

    /**
     * Remove a node from the tracker; do nothing if the node is currently
     * untracked.  This function is main thread only.
     */
    static void Remove(struct Node* node);

    /**
     * Initializes the discard tracker.  This function is main thread only.
     */
    static nsresult Initialize();

    /**
     * Shut the discard tracker down.  This should be called on XPCOM shutdown
     * so we destroy the discard timer's nsITimer.  This function is main thread
     * only.
     */
    static void Shutdown();

    /**
     * Discard the decoded image data for all images tracked by the discard
     * tracker.  This function is main thread only.
     */
    static void DiscardAll();

    /**
     * Inform the discard tracker that we've allocated or deallocated some
     * memory for a decoded image.  We use this to determine when we've
     * allocated too much memory and should discard some images.  This function
     * can be called from any thread and is thread-safe.
     */
    static void InformAllocation(int64_t bytes);

  private:
    /**
     * This is called when the discard timer fires; it calls into DiscardNow().
     */
    friend void DiscardTimeoutChangedCallback(const char* aPref, void *aClosure);

    /**
     * When run, this runnable sets sDiscardRunnablePending to false and calls
     * DiscardNow().
     */
    class DiscardRunnable : public nsRunnable
    {
      NS_IMETHOD Run();
    };

    static void ReloadTimeout();
    static nsresult EnableTimer();
    static void DisableTimer();
    static void MaybeDiscardSoon();
    static void TimerCallback(nsITimer *aTimer, void *aClosure);
    static void DiscardNow();

    static LinkedList<Node> sDiscardableImages;
    static nsCOMPtr<nsITimer> sTimer;
    static bool sInitialized;
    static bool sTimerOn;
    static mozilla::Atomic<bool> sDiscardRunnablePending;
    static int64_t sCurrentDecodedImageBytes;
    static uint32_t sMinDiscardTimeoutMs;
    static uint32_t sMaxDecodedImageKB;
    // Lock for safegarding the 64-bit sCurrentDecodedImageBytes
    static PRLock *sAllocationLock;
    static mozilla::Mutex* sNodeListMutex;
    static Atomic<bool> sShutdown;
};

} // namespace image
} // namespace mozilla

#endif /* mozilla_imagelib_DiscardTracker_h_ */