Emacs Lisp provides a limited form of concurrency, called 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
thread-yield, when waiting for keyboard input or for process
output from asynchronous processes (e.g., during
accept-process-output), or during blocking operations relating
to threads, such as mutex locking or 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 let binding is local. Each
thread also has its own current buffer (see The Current Buffer) and
its own match data (see The Match Data).
Note that 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 let. For example, a
manual implementation of let written using
unwind-protect cannot arrange for variable values to be
thread-specific.
In the case of lexical bindings (see Scoping Rules for Variable Bindings), a closure is an object like any other in Emacs Lisp, and bindings in a closure are shared by any threads invoking the closure.
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.
Create a new thread of execution which invokes function. When 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.
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 name is provided, it must be a string.
buffer-disposition indicates what happens if the thread’s current
buffer is about to be killed. If the value is t, killing the
buffer is not allowed. Any other value, including nil (which is
the default), means that the buffer is killed and the thread is assigned
another current buffer, and it’s signaled the error
thread-buffer-killed. But if the value is the symbol
silently, the error is not signaled.
This function returns the new thread.
After a thread had been created, you can inspect or change its
buffer-disposition using functions thread-buffer-disposition and
thread-set-buffer-disposition.
This function returns t if object represents an Emacs
thread, nil otherwise.
Block until thread exits, or until the current thread is signaled. It returns the result of the thread function. If thread has already exited, this returns immediately.
Like signal (see How to Signal an Error), but the signal is
delivered in the thread thread. If thread is the current
thread, then this just calls signal immediately. Otherwise,
thread will receive the signal as soon as it becomes current.
If thread was blocked by a call to mutex-lock,
condition-wait, or thread-join; thread-signal
will unblock it.
If thread is the main thread, the signal is not propagated there. Instead, it is shown as message in the main thread.
Yield execution to the next runnable thread.
Return the name of thread, as specified to make-thread.
Return t if thread is alive, or nil if it is not.
A thread is alive as long as its function is still executing.
Return the object that thread is waiting on. This function is primarily intended for debugging, and is given a “double hyphen” name to indicate that.
If thread is blocked in thread-join, this returns the
thread for which it is waiting.
If thread is blocked in mutex-lock, this returns the mutex.
If thread is blocked in condition-wait, this returns the
condition variable.
Otherwise, this returns nil.
Return the current thread.
Return a list of all the live thread objects. A new list is returned by each invocation.
This variable keeps the main thread Emacs is running, or nil if
Emacs is compiled without thread support.
When code run by a thread signals an error that is unhandled, the thread exits. Other threads can access the error form which caused the thread to exit using the following function.
This function returns the last error form recorded when a thread
exited due to an error. Each thread that exits abnormally overwrites
the form stored by the previous thread’s error with a new value, so
only the last one can be accessed. If cleanup is
non-nil, the stored form is reset to nil.
A 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 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.
This function returns t if object represents an Emacs
mutex, nil otherwise.
Create a new mutex and return it. If 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.
Return the name of mutex, as specified to make-mutex.
This will block until this thread acquires mutex, or until this
thread is signaled using thread-signal. If mutex is
already owned by this thread, this simply returns.
Release mutex. If mutex is not owned by this thread, this will signal an error.
This macro is the simplest and safest way to evaluate forms while holding a mutex. It acquires mutex, invokes body, and then releases mutex. It returns the result of body.
A 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:
(with-mutex mutex
(while (not global-variable)
(condition-wait cond-var)))
The mutex ensures atomicity, and the loop is for robustness—there 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 notify it:
(with-mutex mutex (setq global-variable (some-computation)) (condition-notify cond-var))
Make a new condition variable associated with mutex. If 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.
This function returns t if object represents a condition
variable, nil otherwise.
Wait for another thread to notify cond, a condition variable.
This function will block until the condition is notified, or until a
signal is delivered to this thread using thread-signal.
It is an error to call condition-wait without holding the
condition’s associated mutex.
condition-wait releases the associated mutex while waiting.
This allows other threads to acquire the mutex in order to notify the
condition.
Notify cond. The mutex with cond must be held before
calling this. Ordinarily a single waiting thread is woken by
condition-notify; but if all is not nil, then all
threads waiting on cond are notified.
condition-notify releases the associated mutex.
This allows other threads to acquire the mutex in order to wait on the
condition.
Return the name of cond, as passed to
make-condition-variable.
Return the mutex associated with cond. Note that the associated mutex cannot be changed.
The list-threads command lists all the currently alive threads.
In the resulting buffer, each thread is identified either by the name
passed to make-thread (see Basic Thread Functions), or by
its unique internal identifier if it was not created with a name. The
status of each thread at the time of the creation or last update of
the buffer is shown, in addition to the object the thread was blocked
on at the time, if it was blocked.
The *Threads* buffer will automatically update twice per second. You can make the refresh rate faster or slower by customizing this variable.
Here are the commands available in the thread list buffer:
Show a backtrace of the thread at point. This will show where in its code the thread had yielded or was blocked at the moment you pressed b. Be aware that the backtrace is a snapshot; the thread could have meanwhile resumed execution, and be in a different state, or could have exited.
You may use g in the thread’s backtrace buffer to get an updated backtrace, as backtrace buffers do not automatically update. See Backtraces, for a description of backtraces and the other commands which work on them.
Signal the thread at point. After s, type q to send a quit signal or e to send an error signal. Threads may implement handling of signals, but the default behavior is to exit on any signal. Therefore you should only use this command if you understand how to restart the target thread, because your Emacs session may behave incorrectly if necessary threads are killed.
Update the list of threads and their statuses.