store.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #ifndef MUPDF_FITZ_STORE_H
  2. #define MUPDF_FITZ_STORE_H
  3. #include "mupdf/fitz/system.h"
  4. #include "mupdf/fitz/context.h"
  5. #include "mupdf/fitz/output.h"
  6. /*
  7. Resource store
  8. MuPDF stores decoded "objects" into a store for potential reuse.
  9. If the size of the store gets too big, objects stored within it can
  10. be evicted and freed to recover space. When MuPDF comes to decode
  11. such an object, it will check to see if a version of this object is
  12. already in the store - if it is, it will simply reuse it. If not, it
  13. will decode it and place it into the store.
  14. All objects that can be placed into the store are derived from the
  15. fz_storable type (i.e. this should be the first component of the
  16. objects structure). This allows for consistent (thread safe)
  17. reference counting, and includes a function that will be called to
  18. free the object as soon as the reference count reaches zero.
  19. Most objects offer fz_keep_XXXX/fz_drop_XXXX functions derived
  20. from fz_keep_storable/fz_drop_storable. Creation of such objects
  21. includes a call to FZ_INIT_STORABLE to set up the fz_storable header.
  22. */
  23. typedef struct fz_storable_s fz_storable;
  24. typedef struct fz_key_storable_s fz_key_storable;
  25. typedef void (fz_store_drop_fn)(fz_context *, fz_storable *);
  26. struct fz_storable_s {
  27. int refs;
  28. fz_store_drop_fn *drop;
  29. };
  30. struct fz_key_storable_s {
  31. fz_storable storable;
  32. short store_key_refs;
  33. };
  34. #define FZ_INIT_STORABLE(S_,RC,DROP) \
  35. do { fz_storable *S = &(S_)->storable; S->refs = (RC); \
  36. S->drop = (DROP); \
  37. } while (0)
  38. #define FZ_INIT_KEY_STORABLE(KS_,RC,DROP) \
  39. do { fz_key_storable *KS = &(KS_)->key_storable; KS->store_key_refs = 0;\
  40. FZ_INIT_STORABLE(KS,RC,DROP); \
  41. } while (0)
  42. void *fz_keep_storable(fz_context *, const fz_storable *);
  43. void fz_drop_storable(fz_context *, const fz_storable *);
  44. void *fz_keep_key_storable(fz_context *, const fz_key_storable *);
  45. int fz_drop_key_storable(fz_context *, const fz_key_storable *);
  46. void *fz_keep_key_storable_key(fz_context *, const fz_key_storable *);
  47. int fz_drop_key_storable_key(fz_context *, const fz_key_storable *);
  48. static inline int fz_key_storable_needs_reaping(fz_context *ctx, const fz_key_storable *ks)
  49. {
  50. return ks == NULL ? 0 : (ks->store_key_refs == ks->storable.refs);
  51. }
  52. /*
  53. The store can be seen as a dictionary that maps keys to fz_storable
  54. values. In order to allow keys of different types to be stored, we
  55. have a structure full of functions for each key 'type'; this
  56. fz_store_type pointer is stored with each key, and tells the store
  57. how to perform certain operations (like taking/dropping a reference,
  58. comparing two keys, outputting details for debugging etc).
  59. The store uses a hash table internally for speed where possible. In
  60. order for this to work, we need a mechanism for turning a generic
  61. 'key' into 'a hashable string'. For this purpose the type structure
  62. contains a make_hash_key function pointer that maps from a void *
  63. to a fz_store_hash structure. If make_hash_key function returns 0,
  64. then the key is determined not to be hashable, and the value is
  65. not stored in the hash table.
  66. Some objects can be used both as values within the store, and as a
  67. component of keys within the store. We refer to these objects as
  68. "key storable" objects. In this case, we need to take additional
  69. care to ensure that we do not end up keeping an item within the
  70. store, purely because its value is referred to by another key in
  71. the store.
  72. An example of this are fz_images in PDF files. Each fz_image is
  73. placed into the store to enable it to be easily reused. When the
  74. image is rendered, a pixmap is generated from the image, and the
  75. pixmap is placed into the store so it can be reused on subsequent
  76. renders. The image forms part of the key for the pixmap.
  77. When we close the pdf document (and any associated pages/display
  78. lists etc), we drop the images from the store. This may leave us
  79. in the position of the images having non-zero reference counts
  80. purely because they are used as part of the keys for the pixmaps.
  81. We therefore use special reference counting functions to keep
  82. track of these "key storable" items, and hence store the number of
  83. references to these items that are used in keys.
  84. When the number of references to an object == the number of
  85. references to an object from keys in the store, we know that we can
  86. remove all the items which have that object as part of the key.
  87. This is done by running a pass over the store, 'reaping' those
  88. items.
  89. Reap passes are slower than we would like as they touch every
  90. item in the store. We therefore provide a way to 'batch' such
  91. reap passes together, using fz_defer_reap_start/fz_defer_reap_end
  92. to bracket a region in which many may be triggered.
  93. */
  94. typedef struct fz_store_hash_s
  95. {
  96. fz_store_drop_fn *drop;
  97. union
  98. {
  99. struct
  100. {
  101. const void *ptr;
  102. int i;
  103. } pi;
  104. struct
  105. {
  106. const void *ptr;
  107. int i;
  108. fz_irect r;
  109. } pir;
  110. struct
  111. {
  112. int id;
  113. float m[4];
  114. } im;
  115. } u;
  116. } fz_store_hash;
  117. typedef struct fz_store_type_s
  118. {
  119. int (*make_hash_key)(fz_context *ctx, fz_store_hash *, void *);
  120. void *(*keep_key)(fz_context *,void *);
  121. void (*drop_key)(fz_context *,void *);
  122. int (*cmp_key)(fz_context *ctx, void *, void *);
  123. void (*print)(fz_context *ctx, fz_output *out, void *);
  124. int (*needs_reap)(fz_context *ctx, void *);
  125. } fz_store_type;
  126. /*
  127. fz_store_new_context: Create a new store inside the context
  128. max: The maximum size (in bytes) that the store is allowed to grow
  129. to. FZ_STORE_UNLIMITED means no limit.
  130. */
  131. void fz_new_store_context(fz_context *ctx, size_t max);
  132. /*
  133. fz_drop_store_context: Drop a reference to the store.
  134. */
  135. void fz_drop_store_context(fz_context *ctx);
  136. /*
  137. fz_keep_store_context: Take a reference to the store.
  138. */
  139. fz_store *fz_keep_store_context(fz_context *ctx);
  140. /*
  141. fz_store_item: Add an item to the store.
  142. Add an item into the store, returning NULL for success. If an item
  143. with the same key is found in the store, then our item will not be
  144. inserted, and the function will return a pointer to that value
  145. instead. This function takes its own reference to val, as required
  146. (i.e. the caller maintains ownership of its own reference).
  147. key: The key used to index the item.
  148. val: The value to store.
  149. itemsize: The size in bytes of the value (as counted towards the
  150. store size).
  151. type: Functions used to manipulate the key.
  152. */
  153. void *fz_store_item(fz_context *ctx, void *key, void *val, size_t itemsize, const fz_store_type *type);
  154. /*
  155. fz_find_item: Find an item within the store.
  156. drop: The function used to free the value (to ensure we get a value
  157. of the correct type).
  158. key: The key used to index the item.
  159. type: Functions used to manipulate the key.
  160. Returns NULL for not found, otherwise returns a pointer to the value
  161. indexed by key to which a reference has been taken.
  162. */
  163. void *fz_find_item(fz_context *ctx, fz_store_drop_fn *drop, void *key, const fz_store_type *type);
  164. /*
  165. fz_remove_item: Remove an item from the store.
  166. If an item indexed by the given key exists in the store, remove it.
  167. drop: The function used to free the value (to ensure we get a value
  168. of the correct type).
  169. key: The key used to find the item to remove.
  170. type: Functions used to manipulate the key.
  171. */
  172. void fz_remove_item(fz_context *ctx, fz_store_drop_fn *drop, void *key, const fz_store_type *type);
  173. /*
  174. fz_empty_store: Evict everything from the store.
  175. */
  176. void fz_empty_store(fz_context *ctx);
  177. /*
  178. fz_store_scavenge: Internal function used as part of the scavenging
  179. allocator; when we fail to allocate memory, before returning a
  180. failure to the caller, we try to scavenge space within the store by
  181. evicting at least 'size' bytes. The allocator then retries.
  182. size: The number of bytes we are trying to have free.
  183. phase: What phase of the scavenge we are in. Updated on exit.
  184. Returns non zero if we managed to free any memory.
  185. */
  186. int fz_store_scavenge(fz_context *ctx, size_t size, int *phase);
  187. /*
  188. fz_shrink_store: Evict items from the store until the total size of
  189. the objects in the store is reduced to a given percentage of its
  190. current size.
  191. percent: %age of current size to reduce the store to.
  192. Returns non zero if we managed to free enough memory, zero otherwise.
  193. */
  194. int fz_shrink_store(fz_context *ctx, unsigned int percent);
  195. typedef int (fz_store_filter_fn)(fz_context *ctx, void *arg, void *key);
  196. void fz_filter_store(fz_context *ctx, fz_store_filter_fn *fn, void *arg, const fz_store_type *type);
  197. /*
  198. fz_print_store: Dump the contents of the store for debugging.
  199. */
  200. void fz_print_store(fz_context *ctx, fz_output *out);
  201. void fz_print_store_locked(fz_context *ctx, fz_output *out);
  202. /*
  203. fz_defer_reap_start: Increment the defer reap count.
  204. No reap operations will take place (except for those
  205. triggered by an immediate failed malloc) until the
  206. defer reap count returns to 0.
  207. Call this at the start of a process during which you
  208. potentially might drop many reapable objects.
  209. It is vital that every fz_defer_reap_start is matched
  210. by a fz_defer_reap_end call.
  211. */
  212. void fz_defer_reap_start(fz_context *ctx);
  213. /*
  214. fz_defer_reap_end: Decrement the defer reap count.
  215. If the defer reap count returns to 0, and the store
  216. has reapable objects in, a reap pass will begin.
  217. Call this at the end of a process during which you
  218. potentially might drop many reapable objects.
  219. It is vital that every fz_defer_reap_start is matched
  220. by a fz_defer_reap_end call.
  221. */
  222. void fz_defer_reap_end(fz_context *ctx);
  223. #endif