Key storable items

Some objects can be used both as values within the Store, and as a component of keys within the Store. We refer to these objects as `key storable' objects. In this case, we need to take additional care to ensure that we do not end up keeping an item within the store purely because its value is referred to by another key in the store.

An example of this are fz_images in PDF files. Each fz_image is placed into the Store to enable it to be easily reused. When the image is rendered, a pixmap is generated from the image, and the pixmap is placed into the Store so it can be reused on subsequent renders. The image forms part of the key for the pixmap.

When we close the pdf document (and any associated pages/display lists etc), we drop the images from the Store. This may leave us in the position of the images having non-zero reference counts purely because they are used as part of the keys for the pixmaps.

The pixmaps can never be found by a search of the Store, because to find them, we'd have to search for them using the appropriate fz_image. They are therefore, to all intents and purposes `dead', and just taking up useless space.

We therefore use special reference counting functions to implement these fz_key_storable items, fz_keep_key_storable and fz_drop_key_storable rather than the more usual fz_keep_storable and fz_drop_storable.

The sole difference is that these enable us to store the number of references to these items that are used in keys. This is achieved by callers taking and dropping references for use in keys with fz_keep_key_storable_key and fz_drop_key_storable_key.

This means that key storable items need to provide two sets of keep and drop functions, one for `normal' callers, and one for use during key handling. For example:


\begin{lstlisting}
fz_image *fz_keep_image(fz_context *ctx, fz_image *image);
vo...
...void fz_drop_image_store_key(fz_context *ctx, fz_image *image);
\end{lstlisting}

The purpose of this extra work is to allow us to spot when we may need to check the Store for `dead' entries - those that can never be found by searching the Store.