[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Are there plans for a multi-threaded Emacs?

From: Martin Stjernholm
Subject: Re: Are there plans for a multi-threaded Emacs?
Date: Mon, 08 Dec 2003 23:02:14 +0100
User-agent: Gnus/5.090016 (Oort Gnus v0.16) Emacs/20.7 (gnu/linux)

David Kastrup <address@hidden> wrote:

> /.../ If I execute some keystrokes that will mark a region and then
> press the delete key before the operation that will mark the region
> actually has completed, I won't be happy if it instead deletes what
> happens to be at the time marked by something else. /.../

That sounds like the first bug that would be fixed after a nonblocking
command loop has been implemented. It's hardly an argument against
such a thing in general. There are still many cases where the
responsiveness can be improved. Threads (or one-shot continuations, if
you like) often makes it easier to accomplish that, especially when it
comes to fixing old applications which are written with blocking
operations (since changing them to be event driven is more or less
turning them inside-out).

As for keyboard input, I don't think one ever wants to parallelize it,
not even when loading a large file or starting Gnus. It could however
be nice to put an executing command "in the background", just like you
can press C-z bg RET in a shell if you find that a command takes too
long. That'd be a really neat feature, actually.

Things that should run in the background by default are instead those
that are trigged by non-user activities, such as timers running out,
network traffic, and display redraws.

If a thread or continuation facitility is implemented, I have some
ideas for the elisp interface to make it comparatively easy to adapt
existing code to a reasonable degree of parallelism (not to be
confused with true multi-cpu parallelism). It's basically the idea
about buffer local threads discussed earlier in this discussion
thread, but outlined in more detail:

o  There are two kinds of locks: One for everything and one for each
   buffer's local data.(*)

o  There is a form similar to `interactive' that declares a function
   to be buffer local.

o  Events that preferably should run in the background (i.e. anything
   but input events from the user, afaics) check if the function being
   called is declared as buffer local.

o  Functions declared as buffer local are allowed to run until they
   access some buffer local data, and the lock for that buffer is then
   taken automatically.

o  The global lock is taken for other functions. That implies taking
   the buffer locks for all buffers. The functions will run just like

o  If only a buffer lock is taken, the function and all code it calls
   are allowed to change the buffer local data. Any attempt to change
   global data will give an error, but reading it is fine.

o  Whenever a buffer local function waits in blocking I/O or is
   preempted (cooperative multitasking isn't necessary), a function
   local to another buffer can run. This is the improvement. Given
   that almost all activities in Emacs are correlated to a single
   buffer, this should be a common situation.

The important points with this model are that it is free from all
possible deadlocks and races, and that it gives good errors which
makes it relatively easy to adapt existing code. To improve the
parallelism of a certain piece of code, simply declare the callback as
buffer local and then run until the global write error occurs.
Investigate the error and remove the global change. Repeat.

The byte compiler can already track call trees. With a bit of work it
could probably be extended to check for global writes from buffer
local functions at compile time.

The locking model can of course be refined further. Primitives should
be available to let the elisp programmer explicitly disable this
safety net and implement custom locking instead, at least to the
extent that several threads holds the same buffer lock (allowing it
for the global lock is more questionable).

*)  Note that these are elisp level locks; on the C level there can
    still be a single "everything" lock without sacrificing
    responsiveness, as has been discussed earlier. That would probably
    avoid considerable internal complexity since things aren't as well
    separated into buffer contexts there as they appear to be on the
    elisp level.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]