1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/src/DiscardTracker.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,140 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_imagelib_DiscardTracker_h_ 1.10 +#define mozilla_imagelib_DiscardTracker_h_ 1.11 + 1.12 +#include "mozilla/Atomics.h" 1.13 +#include "mozilla/LinkedList.h" 1.14 +#include "mozilla/Mutex.h" 1.15 +#include "mozilla/TimeStamp.h" 1.16 +#include "prlock.h" 1.17 +#include "nsThreadUtils.h" 1.18 +#include "nsAutoPtr.h" 1.19 + 1.20 +class nsITimer; 1.21 + 1.22 +namespace mozilla { 1.23 +namespace image { 1.24 + 1.25 +class RasterImage; 1.26 + 1.27 +/** 1.28 + * This static class maintains a linked list of RasterImage objects which are 1.29 + * eligible for discarding. 1.30 + * 1.31 + * When Reset() is called, the node is removed from its position in the list 1.32 + * (if it was there before) and appended to the beginnings of the list. 1.33 + * 1.34 + * Periodically (on a timer and when we notice that we're using more memory 1.35 + * than we'd like for decoded images), we go through the list and discard 1.36 + * decoded data from images at the end of the list. 1.37 + */ 1.38 +class DiscardTracker 1.39 +{ 1.40 + public: 1.41 + /** 1.42 + * The DiscardTracker keeps a linked list of Node objects. Each object 1.43 + * points to a RasterImage and contains a timestamp indicating when the 1.44 + * node was inserted into the tracker. 1.45 + * 1.46 + * This structure is embedded within each RasterImage object, and we do 1.47 + * |mDiscardTrackerNode.img = this| on RasterImage construction. Thus, a 1.48 + * RasterImage must always call DiscardTracker::Remove() in its destructor 1.49 + * to avoid having the tracker point to bogus memory. 1.50 + */ 1.51 + struct Node : public LinkedListElement<Node> 1.52 + { 1.53 + RasterImage *img; 1.54 + TimeStamp timestamp; 1.55 + }; 1.56 + 1.57 + /** 1.58 + * Add an image to the front of the tracker's list, or move it to the front 1.59 + * if it's already in the list. This function is main thread only. 1.60 + */ 1.61 + static nsresult Reset(struct Node* node); 1.62 + 1.63 + /** 1.64 + * Remove a node from the tracker; do nothing if the node is currently 1.65 + * untracked. This function is main thread only. 1.66 + */ 1.67 + static void Remove(struct Node* node); 1.68 + 1.69 + /** 1.70 + * Initializes the discard tracker. This function is main thread only. 1.71 + */ 1.72 + static nsresult Initialize(); 1.73 + 1.74 + /** 1.75 + * Shut the discard tracker down. This should be called on XPCOM shutdown 1.76 + * so we destroy the discard timer's nsITimer. This function is main thread 1.77 + * only. 1.78 + */ 1.79 + static void Shutdown(); 1.80 + 1.81 + /** 1.82 + * Discard the decoded image data for all images tracked by the discard 1.83 + * tracker. This function is main thread only. 1.84 + */ 1.85 + static void DiscardAll(); 1.86 + 1.87 + /** 1.88 + * Inform the discard tracker that we are going to allocate some memory 1.89 + * for a decoded image. We use this to determine when we've allocated 1.90 + * too much memory and should discard some images. This function can be 1.91 + * called from any thread and is thread-safe. If this function succeeds, the 1.92 + * caller is now responsible for ensuring that InformDeallocation is called. 1.93 + */ 1.94 + static bool TryAllocation(uint64_t aBytes); 1.95 + 1.96 + /** 1.97 + * Inform the discard tracker that we've deallocated some memory for a 1.98 + * decoded image. This function can be called from any thread and is 1.99 + * thread-safe. 1.100 + */ 1.101 + static void InformDeallocation(uint64_t aBytes); 1.102 + 1.103 + private: 1.104 + /** 1.105 + * This is called when the discard timer fires; it calls into DiscardNow(). 1.106 + */ 1.107 + friend void DiscardTimeoutChangedCallback(const char* aPref, void *aClosure); 1.108 + 1.109 + /** 1.110 + * When run, this runnable sets sDiscardRunnablePending to false and calls 1.111 + * DiscardNow(). 1.112 + */ 1.113 + class DiscardRunnable : public nsRunnable 1.114 + { 1.115 + NS_IMETHOD Run(); 1.116 + }; 1.117 + 1.118 + static void ReloadTimeout(); 1.119 + static nsresult EnableTimer(); 1.120 + static void DisableTimer(); 1.121 + static void MaybeDiscardSoon(); 1.122 + static void TimerCallback(nsITimer *aTimer, void *aClosure); 1.123 + static void DiscardNow(); 1.124 + 1.125 + static LinkedList<Node> sDiscardableImages; 1.126 + static nsCOMPtr<nsITimer> sTimer; 1.127 + static bool sInitialized; 1.128 + static bool sTimerOn; 1.129 + static mozilla::Atomic<bool> sDiscardRunnablePending; 1.130 + static uint64_t sCurrentDecodedImageBytes; 1.131 + static uint32_t sMinDiscardTimeoutMs; 1.132 + static uint32_t sMaxDecodedImageKB; 1.133 + static uint32_t sHardLimitDecodedImageKB; 1.134 + // Lock for safegarding the 64-bit sCurrentDecodedImageBytes 1.135 + static PRLock *sAllocationLock; 1.136 + static mozilla::Mutex* sNodeListMutex; 1.137 + static Atomic<bool> sShutdown; 1.138 +}; 1.139 + 1.140 +} // namespace image 1.141 +} // namespace mozilla 1.142 + 1.143 +#endif /* mozilla_imagelib_DiscardTracker_h_ */