summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-03-14 17:25:40 +0000
committerRobin Watts <robin.watts@artifex.com>2012-03-14 17:27:42 +0000
commitebd905bf410d0093bf68ff1af2621fc4303ed2bd (patch)
tree0ced5332bfd620453853ab730f45ec770c289d96 /doc
parent1d9a98f81e0cb90fcce893f11cc6dcb66323b242 (diff)
downloadmupdf-ebd905bf410d0093bf68ff1af2621fc4303ed2bd.tar.xz
Update doc/overview.txt with details of multi-thread operation.
Basic instructions on how to safely build and use a mupdf based app that makes use of multiple threads efficiently.
Diffstat (limited to 'doc')
-rw-r--r--doc/overview.txt110
1 files changed, 77 insertions, 33 deletions
diff --git a/doc/overview.txt b/doc/overview.txt
index 25cd0d4b..cb8a69e6 100644
--- a/doc/overview.txt
+++ b/doc/overview.txt
@@ -177,36 +177,80 @@ First off, study the basic usage example in doc/example.c and make
sure you understand how it works as it will be the referenced in this
section too.
-There are two variations of how to create multi-threaded applications:
-
-1) lock-less operation -- in which one thread is requesting pages
- to be drawn and responding to user interface actions, while
- another thread is dedicated to drawing pages. In this scenario
- only one thread owns and manipulates the context and document
- at any one time.
-
-2) using locking -- where one thread is requesting pages to be
- draw and responding to user interface actions, while several
- threads may be drawing pages. In this scenario each thread has
- its own context but they share some global state, for example
- the resource store. An additional constraint
-
-The usage example starts by getting a context from fz_new_context with
-standard memory allocation functions, default resource store size and,
-crucially, no locking.
-
-In a multi-threaded application every thread must have a context. Or
-more specifically, each context can only be used from one thread at a
-time. When starting another thread, do NOT call fz_new_context again;
-instead call fz_clone_context. This creates a context sharing the
-memory allocator, resource store etc.
-
-
-
-
-så utan lås: en gui-tråd som visa progress, en tråd som renderar
-med lås: en gui-tråd som request:ar och flera trådar som renderar
-
-having fitz level display list objects created in
-one thread, consumed as read-only in multiple threads, with locked access
-around a few shared caches
+MuPDF can usefully be built into a multi-threaded application without
+the library needing to know anything threading at all. If the library
+opens a document in one thread, and then sits there as a 'server'
+requesting pages and rendering them for other threads that need them,
+then the library is only ever being called from this one thread.
+
+Other threads can still be used to handle UI requests etc, but as far
+as MuPDF is concerned it is only being used in a single threaded way.
+In this instance, there are no threading issues with MuPDF at all,
+and it can safely be used without any locking, as described in the
+previous sections.
+
+This section will attempt to explain how to use MuPDF in the more
+complex case; where we genuinely want to call the MuPDF library
+concurrently from multiple threads within a single application.
+
+MuPDF can be invoked with a user supplied set of locking functions.
+It uses these to take mutexes around operations that would conflict
+is performed concurrently in multiple threads. By leaving the
+exact implementation of locks to the caller MuPDF remains threading
+library agnostic.
+
+The following simple rules should be followed to ensure that
+multi-threaded operations run smoothly:
+
+1) "No simultaneous calls to MuPDF in different threads are
+ allowed to use the same context."
+
+ Most of the time it is simplest to just use a different
+ context for every thread; just create a new context at the
+ same time as you create the thread.
+
+2) "The document is bound to the context with which it is created."
+
+ All subsequent accesses to the document implicitly use the same
+ context; this means that only 1 thread can ever be accessing
+ the document at once. This does not mean that the document can
+ only be used from one thread ever, though in many cases this
+ is the simplest structure overall.
+
+So, how does a multi-threaded example differ from a non-multithreaded
+one?
+
+Firstly, when we create the first context, we call fz_new_context
+as before, but the second argument should be a pointer to a set
+of locking functions.
+
+The calling code should provide FZ_LOCK_MAX mutexes, which will be
+locked/unlocked by MuPDF calling the lock/unlock function pointers
+in the supplied structure with the user pointer from the structure
+and the lock number, i (0 <= i < FZ_LOCK_MAX). These mutexes can
+safely be recursive or non-recursive as MuPDF only calls in a non
+recursive style.
+
+To make subsequent contexts, the user should NOT call fz_new_context
+again (as this will fail to share important resources such as the
+store and glyphcache), but should rather call fz_clone_context.
+Each of these cloned contexts can be freed by fz_free_context as
+usual.
+
+To open a document, call fz_open_document as usual, passing a context
+and a filename; this context is bound to the document. All future
+calls to access the document will use this context internally.
+
+Only one thread at a time can therefore perform operations such as
+fetching a page, or rendering that page to a display list. Once a
+display list has been obtained however, it can be rendered from any
+other thread (or even from several threads simultaneously, giving
+banded rendering).
+
+This means that an implementer has 2 basic choices when constructing
+an application to use MuPDF in multi-threaded mode. Either he can
+construct it so that a single nominated thread opens the document
+and then acts as a 'server' creating display lists for other threads
+to render, or he can add his own mutex around calls to mupdf that
+use the document. The former is likely to be far more efficient in
+the long run.