From 0ec3764d398add8c038b317201d139aaef4a594e Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 23 Aug 2012 13:58:38 -0600 Subject: first draft of threads documentation --- doc/lispref/threads.texi | 238 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 doc/lispref/threads.texi (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi new file mode 100644 index 00000000000..760452808cf --- /dev/null +++ b/doc/lispref/threads.texi @@ -0,0 +1,238 @@ +@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. + + 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. + +@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. +@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 -- cgit v1.2.1 From c2283a75564d7794fb5f604eafc6b65f71146e7f Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 23 Aug 2012 14:00:38 -0600 Subject: document until-condition --- doc/lispref/threads.texi | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index 760452808cf..8094a68f9aa 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -236,3 +236,9 @@ Return the name of @var{cond}, as passed to 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 -- cgit v1.2.1 From 58c8e9a4debc3ef2c672a34d58720d5bf0530d12 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 24 Aug 2012 09:28:02 -0600 Subject: minor documentation updates --- doc/lispref/threads.texi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index 8094a68f9aa..434915cdbc2 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -27,7 +27,8 @@ 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. +local variables are not---a dynamic @code{let} binding is local. Each +thread also has its own current buffer (@pxref{Current Buffer}). In the case of lexical bindings (@pxref{Variable Scoping}), a closure is an object like any other in Emacs Lisp, and bindings in a @@ -50,6 +51,9 @@ threads can be signaled. 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. -- cgit v1.2.1 From 09d7066e2291651805b7bfd5edbf45562766e122 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 25 Aug 2012 14:09:04 -0600 Subject: minor update to thread-join docs --- doc/lispref/threads.texi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index 434915cdbc2..5c4c62f2c06 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -67,7 +67,9 @@ thread, @code{nil} otherwise. @end defun @defun thread-join thread -Block until @var{thread} exits, or until the current thread is signaled. +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 -- cgit v1.2.1 From 303324a9232dbc89369faceb6b3530740d0fc1bd Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 4 Sep 2012 09:37:58 -0600 Subject: link from thread docs to match data --- doc/lispref/threads.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index 5c4c62f2c06..d7e4b0ab2ae 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -28,7 +28,8 @@ 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}). +thread also has its own current buffer (@pxref{Current Buffer}) and +its own match data (@pxref{Match Data}). In the case of lexical bindings (@pxref{Variable Scoping}), a closure is an object like any other in Emacs Lisp, and bindings in a -- cgit v1.2.1 From 63d535c829a930207b64fe733228f15a554644b1 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sun, 23 Dec 2012 15:14:19 -0700 Subject: mention let bindings and lack of other ways to rewind --- doc/lispref/threads.texi | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index d7e4b0ab2ae..9c333546040 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -31,6 +31,13 @@ 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. -- cgit v1.2.1 From 8c46d17826ae89bfa22b5e8048c013c0e3a38b2d Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 27 Aug 2013 12:57:18 -0600 Subject: rename thread-blocker to thread--blocker --- doc/lispref/threads.texi | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index 9c333546040..c846993172f 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Emacs Lisp Reference Manual. -@c Copyright (C) 2012 +@c Copyright (C) 2012, 2013 @c Free Software Foundation, Inc. @c See the file elisp.texi for copying conditions. @node Threads @@ -101,9 +101,10 @@ 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 +@defun thread--blocker thread Return the object that @var{thread} is waiting on. This function is -primarily intended for debugging. +primarily intended for debugging, and is given a ``double hyphen'' +name to indicate that. If @var{thread} is blocked in @code{thread-join}, this returns the thread for which it is waiting. -- cgit v1.2.1 From c1456e303a4502f637a87681dd623f589c25ed23 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 27 Aug 2013 13:07:14 -0600 Subject: zap until-condition docs --- doc/lispref/threads.texi | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index c846993172f..b3a70ee215c 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -192,8 +192,7 @@ and waiting on the condition variable. For example: @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. +may be spurious notifications. Similarly, the mutex must be held before notifying the condition. The typical, and best, approach is to acquire the mutex, make the @@ -251,9 +250,3 @@ Return the name of @var{cond}, as passed to 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 -- cgit v1.2.1 From 0e82377a2d9d8f815d2ef4ec09dc914f37fc87ac Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 27 Aug 2013 13:10:59 -0600 Subject: use condition-notify in the docs, not condition-signal --- doc/lispref/threads.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc/lispref/threads.texi') diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index b3a70ee215c..6237392db3a 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -196,12 +196,12 @@ may be spurious notifications. 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: +changes associated with this condition, and then notify it: @example (with-mutex mutex (setq global-variable (some-computation)) - (condition-signal cond-var)) + (condition-notify cond-var)) @end example @defun make-condition-variable mutex &optional name -- cgit v1.2.1