[Top][All Lists]

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

Re: Concurrency via isolated process/thread

From: Ihor Radchenko
Subject: Re: Concurrency via isolated process/thread
Date: Mon, 24 Jul 2023 13:02:26 +0000

Eli Zaretskii <eliz@gnu.org> writes:

>> Would it be acceptable to convert buffer PT, BEGV, and ZV into
>> thread-local for current cooperative threads?
> General note: it is very hard to have a serious discussion of this
> kind of subject when the goals are not clearly announced, and there
> are gaps of week or two between messages.  Discussing several separate
> aspects of this makes this even harder to follow and respond in a
> useful manner.

I was initially exploring what should be done allow async threads in
Emacs. The discussion established several important global states in
Emacs that must be changed. Then, I explored if those blockers are
possible to solve. Now, I believe that all the blockers can be solved,
if we accept to leave GC and redisplay synchronous.

However, reducing the global state will not be easy and should better be
done in steps. Ideally, steps that can be tested using the existing
synchronous thread paradigm.

The first step, that can also be potentially useful even if I fail to
proceed far enough to get async threads, is removing global point and
restriction state.

>> 1. Removing pt, pt_byte, begv, begv_byte, zv, zv_byte, pt_marker_,
>>    begv_marker_, and zv_marker_ from buffer objects.
>> 2. Adding pt/begv/zv to thread object.
>> 3. Adding an alist linking buffers and past
>>    pt/begv/zv positions visited by a given thread.
>> This way, when a thread yields and later continues executing, its point
>> and restriction will not be changed.
> Why is the last sentence a worthy goal? what do you think will be the
> advantage of that?

Consider a simple regexp search running in a thread:

(while (re-search-forward re nil t)

This search will fail if another thread ever moves point or changes
restriction in the same buffer.

The obvious

(while (re-search-forward re nil t)
  (save-restriction (save-excursion (thread-yield))))

won't work.

So, one would have to go through awkward

(let ((marker (point-marker)))
 (while (re-search-forward re nil t)
  (move-marker marker (point))
  (goto-char marker)))

at least. But it will yet fail if we need to maintain buffer
restriction. So, the code becomes

(let ((marker (point-marker)) (begv (point-min-marker)) (zv (point-max-marker)))
 (while (re-search-forward re nil t)
  (move-marker marker (point))
  (narrow-to-region begv zv)
  (goto-char marker)))

And this may still fail because of unreproducible bugs.

Not to mention that we do not always know where the thread will yield.
Any function may be adviced by user to contain some interactive query,
which will also trigger thread yield.

The above example is just the trivial regexp search. When the code
becomes more complex, things gets even more chaotic and threads become
simply unusable for anything that is trying to scan buffer text.

That's why I think that having threads store their own point and
restriction is useful, even without considering that it will reduce the
global state.

Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

reply via email to

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