  
  [1X5 Caching techniques[0X
  
  
  [1X5.1 The idea of caching[0X
  
  If one wants to work with a large number of large objects which require some
  time  to  prepare  and one does not know beforehand, how often one will need
  each  one, it makes sense to work with some sort of cache. A cache is a data
  structure  to  keep some of the objects already produced but not too many of
  them to waste a lot of memory. That is, objects which have not been used for
  some  time  can automatically be removed from the cache, whereas the objects
  which  are used more frequently stay in the cache. This chapter describes an
  implementation of this idea used in the orbit-by-suborbit algorithms.
  
  
  [1X5.2 Using caches[0X
  
  A cache is created using the following operation:
  
  [1X5.2-1 LinkedListCache[0m
  
  [2X> LinkedListCache( [0X[3Xmemorylimit[0X[2X ) __________________________________[0Xoperation
  [6XReturns:[0X  A new cache object
  
  This operation creates a new linked list cache that uses at most [3Xmemorylimit[0m
  bytes  to  store its entries. The cache is organised as a linked list, newly
  cached  objects  are  appended  at  the beginning of the list, when the used
  memory grows over the limit, old objects are removed at the end of this list
  automatically.
  
  New objects are entered into the hash with the following function:
  
  [1X5.2-2 CacheObject[0m
  
  [2X> CacheObject( [0X[3Xc, ob, mem[0X[2X ) _______________________________________[0Xoperation
  [6XReturns:[0X  A new node in the linked list cache
  
  This operation enters the object [3Xob[0m into the cache [3Xc[0m. The argument [3Xmem[0m is an
  integer  with  the memory usage of the object [3Xob[0m. The object is prepended to
  the  linked  list cache and enough objects at the end are removed to enforce
  the memory usage limit.
  
  [1X5.2-3 ClearCache[0m
  
  [2X> ClearCache( [0X[3Xc[0X[2X ) _________________________________________________[0Xoperation
  [6XReturns:[0X  Nothing
  
  Completely clears the cache [3Xc[0m removing all nodes.
  
  A  linked  list  cache  is  used as follows: Whenever you compute one of the
  objects  you  store it in the cache using [2XCacheObject[0m ([14X5.2-2[0m) and retain the
  linked  list node that is returned. The usual place to retain it would be in
  a  weak pointer object, such that this reference does not prevent the object
  to  be  garbage  collected.  When  you  next need this object, you check its
  corresponding position in the weak pointer object, if the reference is still
  there,  you just use it and tell the cache that it was used again by calling
  [2XUseCacheObject[0m  ([14X5.2-4[0m),  otherwise  you  create it anew and store it in the
  cache again.
  
  As long as the object stays in the cache it is not garbage collected and the
  weak  pointer object will still have its reference. As soon as the object is
  thrown  out of the cache, the only reference to its node is the weak pointer
  object,  thus  if a garbage collection happens, it can be garbage collected.
  Note  that before that garbage collection happens, the object might still be
  accessible  via  the  weak  pointer  object. In this way, the available main
  memory  in  the  workspace  is  used  very  efficiently  and  can  be  freed
  immediately when needed.
  
  [1X5.2-4 UseCacheObject[0m
  
  [2X> UseCacheObject( [0X[3Xc, r[0X[2X ) __________________________________________[0Xoperation
  [6XReturns:[0X  Nothing
  
  The  argument  [3Xc[0m  must  be a cache object and [3Xr[0m a node for such a cache. The
  object  is  either  moved to the front of the linked list (if it is still in
  the  cache) or it is re-cached. If necessary, objects at the end are removed
  from the cache to enforce the memory usage limit.
  
