diff options
Diffstat (limited to 'doc/lispref')
-rw-r--r-- | doc/lispref/Makefile.in | 1 | ||||
-rw-r--r-- | doc/lispref/elisp.texi | 8 | ||||
-rw-r--r-- | doc/lispref/objects.texi | 20 | ||||
-rw-r--r-- | doc/lispref/processes.texi | 30 | ||||
-rw-r--r-- | doc/lispref/threads.texi | 258 |
5 files changed, 312 insertions, 5 deletions
diff --git a/doc/lispref/Makefile.in b/doc/lispref/Makefile.in index 19cf2cc4a5d..c548b67d4ca 100644 --- a/doc/lispref/Makefile.in +++ b/doc/lispref/Makefile.in @@ -97,6 +97,7 @@ srcs = \ $(srcdir)/symbols.texi \ $(srcdir)/syntax.texi \ $(srcdir)/text.texi \ + $(srcdir)/threads.texi \ $(srcdir)/tips.texi \ $(srcdir)/variables.texi \ $(srcdir)/windows.texi \ diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi index 59bbdec0229..0d9432d5e01 100644 --- a/doc/lispref/elisp.texi +++ b/doc/lispref/elisp.texi @@ -221,6 +221,7 @@ To view this manual in other formats, click * Syntax Tables:: The syntax table controls word and list parsing. * Abbrevs:: How Abbrev mode works, and its data structures. +* Threads:: Concurrency in Emacs Lisp. * Processes:: Running and communicating with subprocesses. * Display:: Features for controlling the screen display. * System Interface:: Getting the user id, system type, environment @@ -1290,6 +1291,12 @@ Abbrevs and Abbrev Expansion * Abbrev Table Properties:: How to read and set abbrev table properties. Which properties have which effect. +Threads + +* Basic Thread Functions:: Basic thread functions. +* Mutexes:: Mutexes allow exclusive access to data. +* Condition Variables:: Inter-thread events. + Processes * Subprocess Creation:: Functions that start subprocesses. @@ -1590,6 +1597,7 @@ Object Internals @include searching.texi @include syntax.texi @include abbrevs.texi +@include threads.texi @include processes.texi @include display.texi diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index 3b7dc41335b..61007cc5a12 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -1897,6 +1897,15 @@ with references to further information. @item string-or-null-p @xref{Predicates for Strings, string-or-null-p}. + +@item threadp +@xref{Basic Thread Functions, threadp}. + +@item mutexp +@xref{Mutexes, mutexp}. + +@item condition-variable-p +@xref{Condition Variables, condition-variable-p}. @end table The most general way to check the type of an object is to call the @@ -1910,11 +1919,12 @@ types. In most cases, it is more convenient to use type predicates than This function returns a symbol naming the primitive type of @var{object}. The value is one of the symbols @code{bool-vector}, @code{buffer}, @code{char-table}, @code{compiled-function}, -@code{cons}, @code{float}, @code{font-entity}, @code{font-object}, -@code{font-spec}, @code{frame}, @code{hash-table}, @code{integer}, -@code{marker}, @code{overlay}, @code{process}, @code{string}, -@code{subr}, @code{symbol}, @code{vector}, @code{window}, or -@code{window-configuration}. +@code{condition-variable}, @code{cons}, @code{float}, +@code{font-entity}, @code{font-object}, @code{font-spec}, +@code{frame}, @code{hash-table}, @code{integer}, @code{marker}, +@code{mutex}, @code{overlay}, @code{process}, @code{string}, +@code{subr}, @code{symbol}, @code{thread}, @code{vector}, +@code{window}, or @code{window-configuration}. @example (type-of 1) diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 1181244a974..e869bb86e40 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -1174,6 +1174,7 @@ shell command. * Filter Functions:: Filter functions accept output from the process. * Decoding Output:: Filters can get unibyte or multibyte strings. * Accepting Output:: How to wait until process output arrives. +* Processes and Threads:: How processes and threads interact. @end menu @node Process Buffers @@ -1504,6 +1505,35 @@ did get some output, or @code{nil} if the timeout expired before output arrived. @end defun +@node Processes and Threads +@subsection Processes and Threads +@cindex processes, threads + + Because threads were a relatively late addition to Emacs Lisp, and +due to the way dynamic binding was sometimes used in conjunction with +@code{accept-process-output}, by default a process is locked to the +thread that created it. When a process is locked to a thread, output +from the process can only be accepted by that thread. + + A Lisp program can specify to which thread a process is to be +locked, or instruct Emacs to unlock a process, in which case its +output can be processed by any thread. Only a single thread will wait +for output from a given process at one time---once one thread begins +waiting for output, the process is temporarily locked until +@code{accept-process-output} or @code{sit-for} returns. + + If the thread exits, all the processes locked to it are unlocked. + +@defun process-thread process +Return the thread to which @var{process} is locked. If @var{process} +is unlocked, return @code{nil}. +@end defun + +@defun set-process-thread process thread +Set the locking thread of @var{process} to @var{thread}. @var{thread} +may be @code{nil}, in which case the process is unlocked. +@end defun + @node Sentinels @section Sentinels: Detecting Process Status Changes @cindex process sentinel diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi new file mode 100644 index 00000000000..9c333546040 --- /dev/null +++ b/doc/lispref/threads.texi @@ -0,0 +1,258 @@ +@c -*-texinfo-*- +@c This is part of the GNU Emacs Lisp Reference Manual. +@c Copyright (C) 2012 +@c Free Software Foundation, Inc. +@c See the file elisp.texi for copying conditions. +@node Threads +@chapter Threads +@cindex threads +@cindex concurrency + + Emacs Lisp provides a limited form of concurrency, called +@dfn{threads}. All the threads in a given instance of Emacs share the +same memory. Concurrency in Emacs Lisp is ``mostly cooperative'', +meaning that Emacs will only switch execution between threads at +well-defined times. However, the Emacs thread support has been +designed in a way to later allow more fine-grained concurrency, and +correct programs should not rely on cooperative threading. + + Currently, thread switching will occur upon explicit request via +@code{thread-yield}, when waiting for keyboard input or for process +output (e.g., during @code{accept-process-output}), or during blocking +operations relating to threads, such as mutex locking or +@code{thread-join}. + + Emacs Lisp provides primitives to create and control threads, and +also to create and control mutexes and condition variables, useful for +thread synchronization. + + While global variables are shared among all Emacs Lisp threads, +local variables are not---a dynamic @code{let} binding is local. Each +thread also has its own current buffer (@pxref{Current Buffer}) and +its own match data (@pxref{Match Data}). + + Note that @code{let} bindings are treated specially by the Emacs +Lisp implementation. There is no way to duplicate this unwinding and +rewinding behavior other than by using @code{let}. For example, a +manual implementation of @code{let} written using +@code{unwind-protect} cannot arrange for variable values to be +thread-specific. + + In the case of lexical bindings (@pxref{Variable Scoping}), a +closure is an object like any other in Emacs Lisp, and bindings in a +closure are shared by any threads invoking the closure. + +@menu +* Basic Thread Functions:: Basic thread functions. +* Mutexes:: Mutexes allow exclusive access to data. +* Condition Variables:: Inter-thread events. +@end menu + +@node Basic Thread Functions +@section Basic Thread Functions + + Threads can be created and waited for. A thread cannot be exited +directly, but the current thread can be exited implicitly, and other +threads can be signaled. + +@defun make-thread function &optional name +Create a new thread of execution which invokes @var{function}. When +@var{function} returns, the thread exits. + +The new thread is created with no local variable bindings in effect. +The new thread's current buffer is inherited from the current thread. + +@var{name} can be supplied to give a name to the thread. The name is +used for debugging and informational purposes only; it has no meaning +to Emacs. If @var{name} is provided, it must be a string. + +This function returns the new thread. +@end defun + +@defun threadp object +This function returns @code{t} if @var{object} represents an Emacs +thread, @code{nil} otherwise. +@end defun + +@defun thread-join thread +Block until @var{thread} exits, or until the current thread is +signaled. If @var{thread} has already exited, this returns +immediately. +@end defun + +@defun thread-signal thread error-symbol data +Like @code{signal} (@pxref{Signaling Errors}), but the signal is +delivered in the thread @var{thread}. If @var{thread} is the current +thread, then this just calls @code{signal} immediately. +@code{thread-signal} will cause a thread to exit a call to +@code{mutex-lock}, @code{condition-wait}, or @code{thread-join}. +@end defun + +@defun thread-yield +Yield execution to the next runnable thread. +@end defun + +@defun thread-name thread +Return the name of @var{thread}, as specified to @code{make-thread}. +@end defun + +@defun thread-alive-p thread +Return @code{t} if @var{thread} is alive, or @code{nil} if it is not. +A thread is alive as long as its function is still executing. +@end defun + +@defun thread-blocker thread +Return the object that @var{thread} is waiting on. This function is +primarily intended for debugging. + +If @var{thread} is blocked in @code{thread-join}, this returns the +thread for which it is waiting. + +If @var{thread} is blocked in @code{mutex-lock}, this returns the mutex. + +If @var{thread} is blocked in @code{condition-wait}, this returns the +condition variable. + +Otherwise, this returns @code{nil}. +@end defun + +@defun current-thread +Return the current thread. +@end defun + +@defun all-threads +Return a list of all the live thread objects. A new list is returned +by each invocation. +@end defun + +@node Mutexes +@section Mutexes + + A @dfn{mutex} is an exclusive lock. At any moment, zero or one +threads may own a mutex. If a thread attempts to acquire a mutex, and +the mutex is already owned by some other thread, then the acquiring +thread will block until the mutex becomes available. + + Emacs Lisp mutexes are of a type called @dfn{recursive}, which means +that a thread can re-acquire a mutex it owns any number of times. A +mutex keeps a count of how many times it has been acquired, and each +acquisition of a mutex must be paired with a release. The last +release by a thread of a mutex reverts it to the unowned state, +potentially allowing another thread to acquire the mutex. + +@defun mutexp object +This function returns @code{t} if @var{object} represents an Emacs +mutex, @code{nil} otherwise. +@end defun + +@defun make-mutex &optional name +Create a new mutex and return it. If @var{name} is specified, it is a +name given to the mutex. It must be a string. The name is for +debugging purposes only; it has no meaning to Emacs. +@end defun + +@defun mutex-name mutex +Return the name of @var{mutex}, as specified to @code{make-mutex}. +@end defun + +@defun mutex-lock mutex +This will block until this thread acquires @var{mutex}, or until this +thread is signaled using @code{thread-signal}. If @var{mutex} is +already owned by this thread, this simply returns. +@end defun + +@defun mutex-unlock mutex +Release @var{mutex}. If @var{mutex} is not owned by this thread, this +will signal an error. +@end defun + +@defmac with-mutex mutex body@dots{} +This macro is the simplest and safest way to evaluate forms while +holding a mutex. It acquires @var{mutex}, invokes @var{body}, and +then releases @var{mutex}. It returns the result of @var{body}. +@end defmac + +@node Condition Variables +@section Condition Variables + + A @dfn{condition variable} is a way for a thread to block until some +event occurs. A thread can wait on a condition variable, to be woken +up when some other thread notifies the condition. + + A condition variable is associated with a mutex and, conceptually, +with some condition. For proper operation, the mutex must be +acquired, and then a waiting thread must loop, testing the condition +and waiting on the condition variable. For example: + +@example +(with-mutex mutex + (while (not global-variable) + (condition-wait cond-var))) +@end example + + The mutex ensures atomicity, and the loop is for robustness---there +may be spurious notifications. Emacs Lisp provides a macro, +@code{until-condition}, to do this automatically. + + Similarly, the mutex must be held before notifying the condition. +The typical, and best, approach is to acquire the mutex, make the +changes associated with this condition, and then signal it: + +@example +(with-mutex mutex + (setq global-variable (some-computation)) + (condition-signal cond-var)) +@end example + +@defun make-condition-variable mutex &optional name +Make a new condition variable associated with @var{mutex}. If +@var{name} is specified, it is a name given to the condition variable. +It must be a string. The name is for debugging purposes only; it has +no meaning to Emacs. +@end defun + +@defun condition-variable-p object +This function returns @code{t} if @var{object} represents a condition +variable, @code{nil} otherwise. +@end defun + +@defun condition-wait cond +Wait for another thread to notify @var{cond}, a condition variable. +This function will block until the condition is notified, or until a +signal is delivered to this thread using @code{thread-signal}. + +It is an error to call @code{condition-wait} without holding the +condition's associated mutex. + +@code{condition-wait} releases the associated mutex while waiting. +This allows other threads to acquire the mutex in order to notify the +condition. +@end defun + +@defun condition-notify cond &optional all +Notify @var{cond}. The mutex with @var{cond} must be held before +calling this. Ordinarily a single waiting thread is woken by +@code{condition-notify}; but if @var{all} is not @code{nil}, then all +threads waiting on @var{cond} are notified. + +@code{condition-notify} releases the associated mutex while waiting. +This allows other threads to acquire the mutex in order to wait on the +condition. +@c why bother? +@end defun + +@defun condition-name cond +Return the name of @var{cond}, as passed to +@code{make-condition-variable}. +@end defun + +@defun condition-mutex cond +Return the mutex associated with @var{cond}. Note that the associated +mutex cannot be changed. +@end defun + +@defmac until-condition test cond +Acquire the mutex associated with @var{cond}, and then loop, invoking +the form @var{test}. If @var{test} evaluates to @code{nil}, invoke +@code{condition-wait} on @var{cond}. +@end defmac |