summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-09-15 16:37:42 +0100
committerRobin Watts <robin.watts@artifex.com>2016-09-16 14:00:32 +0100
commit3de83b0d7a679c2c91587718c1c273775b99e8dd (patch)
tree72a42a88b82c5c3d4a30c52d4df370bb0700fb38 /include
parent3a1ae9b3db655efc98965bcc82ad545f6572158d (diff)
downloadmupdf-3de83b0d7a679c2c91587718c1c273775b99e8dd.tar.xz
Extend store to cope with references used in keys.
The store is effectively a list of items, where each item is a (key, value) pair. The design is such that we can easily get into the state where the only reference to a value is that held by the store. Subsequent references can then be generated by things being 'found' from within the store. While the only reference to an object is that held by it being a value in the store, the store is free to evict it to save memory. Images present a complication to this design; images are stored both as values within the store (by the pdf agent, so that we do not regenerate images each time we meet them in the file), and as parts of the keys within the store. For example, once an image is decoded to give a pixmap, the pixmap is cached in the store. The key to look that pixmap up again includes a reference to the image from which the pixmap was generated. This means, that for document handlers such as gproof that do not place images in the store, we can end up with images that are kept around purely by dint of being used as references in store keys. There is no chance of the value (the decoded pixmap) ever being 'found' from the store as no one other than the key is holding a reference to the image required. Thus the images/pixmaps are never freed until the store is emptied. This commit offers a fix for this situation. Standard store items are based on an fz_storable type. Here we introduce a new fz_key_storable type derived from that. As well as keeping track of the number of references a given item has to it, it keeps a separate count of the number of references a given item has to it from keys in the store. On dropping a reference, we check to see if the number of references has become the same as the number of references from keys in the store. If it has, then we know that these keys can never be 'found' again. So we filter them out of the store, which drops the items.
Diffstat (limited to 'include')
-rw-r--r--include/mupdf/fitz/image.h5
-rw-r--r--include/mupdf/fitz/store.h21
2 files changed, 25 insertions, 1 deletions
diff --git a/include/mupdf/fitz/image.h b/include/mupdf/fitz/image.h
index 6482e80e..cc521904 100644
--- a/include/mupdf/fitz/image.h
+++ b/include/mupdf/fitz/image.h
@@ -68,6 +68,9 @@ void fz_drop_image_base(fz_context *ctx, fz_image *image);
*/
fz_image *fz_keep_image(fz_context *ctx, fz_image *image);
+fz_image *fz_keep_image_store_key(fz_context *ctx, fz_image *image);
+void fz_drop_image_store_key(fz_context *ctx, fz_image *image);
+
typedef void (fz_drop_image_fn)(fz_context *ctx, fz_image *image);
typedef fz_pixmap *(fz_image_get_pixmap_fn)(fz_context *, fz_image *, fz_irect *, int, int, int *);
typedef size_t (fz_image_get_size_fn)(fz_context *, fz_image *);
@@ -85,7 +88,7 @@ size_t fz_image_size(fz_context *ctx, fz_image *im);
struct fz_image_s
{
- fz_storable storable;
+ fz_key_storable key_storable;
int w, h;
uint8_t n;
uint8_t bpc;
diff --git a/include/mupdf/fitz/store.h b/include/mupdf/fitz/store.h
index 07f6a286..2ef9810b 100644
--- a/include/mupdf/fitz/store.h
+++ b/include/mupdf/fitz/store.h
@@ -26,6 +26,7 @@
*/
typedef struct fz_storable_s fz_storable;
+typedef struct fz_key_storable_s fz_key_storable;
typedef void (fz_store_drop_fn)(fz_context *, fz_storable *);
@@ -34,14 +35,30 @@ struct fz_storable_s {
fz_store_drop_fn *drop;
};
+struct fz_key_storable_s {
+ fz_storable storable;
+ int store_key_refs;
+};
+
#define FZ_INIT_STORABLE(S_,RC,DROP) \
do { fz_storable *S = &(S_)->storable; S->refs = (RC); \
S->drop = (DROP); \
} while (0)
+#define FZ_INIT_KEY_STORABLE(KS_,RC,DROP) \
+ do { fz_key_storable *KS = &(KS_)->key_storable; KS->store_key_refs = 0;\
+ FZ_INIT_STORABLE(KS,RC,DROP); \
+ } while (0)
+
void *fz_keep_storable(fz_context *, const fz_storable *);
void fz_drop_storable(fz_context *, const fz_storable *);
+void *fz_keep_key_storable(fz_context *, const fz_key_storable *);
+int fz_drop_key_storable(fz_context *, const fz_key_storable *);
+
+void *fz_keep_key_storable_key(fz_context *, const fz_key_storable *);
+void fz_drop_key_storable_key(fz_context *, const fz_key_storable *);
+
/*
The store can be seen as a dictionary that maps keys to fz_storable
values. In order to allow keys of different types to be stored, we
@@ -192,6 +209,10 @@ int fz_store_scavenge(fz_context *ctx, size_t size, int *phase);
*/
int fz_shrink_store(fz_context *ctx, unsigned int percent);
+typedef int (fz_store_filter_fn)(fz_context *ctx, void *arg, void *key);
+
+void fz_filter_store(fz_context *ctx, fz_store_filter_fn *fn, void *arg, fz_store_type *type);
+
/*
fz_print_store: Dump the contents of the store for debugging.
*/