Classes | Public Member Functions | Protected Member Functions | Friends

nsExpirationTracker< T, K > Class Template Reference

nsExpirationTracker can track the lifetimes and usage of a large number of objects, and send a notification some window of time after a live object was last used. More...

#include <nsExpirationTracker.h>

Collaboration diagram for nsExpirationTracker< T, K >:

List of all members.

Classes

class  Iterator

Public Member Functions

 nsExpirationTracker (PRUint32 aTimerPeriod)
 Initialize the tracker.
 ~nsExpirationTracker ()
nsresult AddObject (T *aObj)
 Add an object to be tracked.
void RemoveObject (T *aObj)
 Remove an object from the tracker.
nsresult MarkUsed (T *aObj)
 Notify that an object has been used.
void AgeOneGeneration ()
 The timer calls this, but it can also be manually called if you want to age objects "artifically".
void AgeAllGenerations ()
 This just calls AgeOneGeneration K times.

Protected Member Functions

virtual void NotifyExpired (T *aObj)=0
 This must be overridden to catch notifications.

Friends

class Iterator

Detailed Description

template<class T, PRUint32 K>
class nsExpirationTracker< T, K >

nsExpirationTracker can track the lifetimes and usage of a large number of objects, and send a notification some window of time after a live object was last used.

This is very useful when you manage a large number of objects and want to flush some after they haven't been used for a while. nsExpirationTracker is designed to be very space and time efficient.

The type parameter T is the object type that we will track pointers to. T must include an accessible method GetExpirationState() that returns a pointer to an nsExpirationState associated with the object (preferably, stored in a field of the object).

The parameter K is the number of generations that will be used. Increasing the number of generations narrows the window within which we promise to fire notifications, at a slight increase in space cost for the tracker. We require 2 <= K <= nsExpirationState::NOT_TRACKED (currently 15).

To use this class, you need to inherit from it and override the NotifyExpired() method.

The approach is to track objects in K generations. When an object is accessed it moves from its current generation to the newest generation. Generations are stored in a cyclic array; when a timer interrupt fires, we advance the current generation pointer to effectively age all objects very efficiently. By storing information in each object about its generation and index within its generation array, we make removal of objects from a generation very cheap.

Future work: -- Add a method to change the timer period?


Constructor & Destructor Documentation

template<class T, PRUint32 K>
nsExpirationTracker< T, K >::nsExpirationTracker ( PRUint32  aTimerPeriod  )  [inline]

Initialize the tracker.

Parameters:
aTimerPeriod the timer period in milliseconds. The guarantees provided by the tracker are defined in terms of this period. If the period is zero, then we don't use a timer and rely on someone calling AgeOneGeneration explicitly.
template<class T, PRUint32 K>
nsExpirationTracker< T, K >::~nsExpirationTracker (  )  [inline]

Member Function Documentation

template<class T, PRUint32 K>
nsresult nsExpirationTracker< T, K >::AddObject ( T *  aObj  )  [inline]

Add an object to be tracked.

It must not already be tracked. It will be added to the newest generation, i.e., as if it was just used.

Returns:
an error on out-of-memory
template<class T, PRUint32 K>
void nsExpirationTracker< T, K >::AgeAllGenerations (  )  [inline]

This just calls AgeOneGeneration K times.

Under normal circumstances this will result in all objects getting NotifyExpired called on them, but if NotifyExpired itself marks some objects as used, then those objects might not expire. This would be a good thing to call if we get into a critically-low memory situation.

template<class T, PRUint32 K>
void nsExpirationTracker< T, K >::AgeOneGeneration (  )  [inline]

The timer calls this, but it can also be manually called if you want to age objects "artifically".

This can result in calls to NotifyExpired.

template<class T, PRUint32 K>
nsresult nsExpirationTracker< T, K >::MarkUsed ( T *  aObj  )  [inline]

Notify that an object has been used.

Returns:
an error if we lost the object from the tracker...
template<class T, PRUint32 K>
virtual void nsExpirationTracker< T, K >::NotifyExpired ( T *  aObj  )  [protected, pure virtual]

This must be overridden to catch notifications.

It is called whenever we detect that an object has not been used for at least (K-1)*mTimerPeriod seconds. If timer events are not delayed, it will be called within roughly K*mTimerPeriod seconds after the last use. (Unless AgeOneGeneration or AgeAllGenerations have been called to accelerate the aging process.)

NOTE: These bounds ignore delays in timer firings due to actual work being performed by the browser. We use a slack timer so there is always at least mTimerPeriod milliseconds between firings, which gives us (K-1)*mTimerPeriod as a pretty solid lower bound. The upper bound is rather loose, however. If the maximum amount by which any given timer firing is delayed is D, then the upper bound before NotifyExpired is called is K*(mTimerPeriod + D).

The NotifyExpired call is expected to remove the object from the tracker, but it need not. The object (or other objects) could be "resurrected" by calling MarkUsed() on them, or they might just not be removed. Any objects left over that have not been resurrected or removed are placed in the new newest-generation, but this is considered "bad form" and should be avoided (we'll issue a warning). (This recycling counts as "a use" for the purposes of the expiry guarantee above...)

For robustness and simplicity, we allow objects to be notified more than once here in the same timer tick.

Implemented in gfxFontCache.

template<class T, PRUint32 K>
void nsExpirationTracker< T, K >::RemoveObject ( T *  aObj  )  [inline]

Remove an object from the tracker.

It must currently be tracked.


Friends And Related Function Documentation

template<class T, PRUint32 K>
friend class Iterator [friend]

The documentation for this class was generated from the following file: