From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Re: Concurrency via isolated process/thread Date: Sun, 09 Jul 2023 19:35:23 +0300 Message-ID: <838rbp9h6c.fsf@gnu.org> References: <871qhnr4ty.fsf@localhost> <87zg49xfke.fsf@localhost> <83sfa1gjns.fsf@gnu.org> <87r0plxbep.fsf@localhost> <83ilawhpi6.fsf@gnu.org> <87zg48apwr.fsf@localhost> <83edljg8ub.fsf@gnu.org> <87o7knbxr7.fsf@localhost> <838rbrg4mg.fsf@gnu.org> <87ilavbvdr.fsf@localhost> <834jmffvhy.fsf@gnu.org> <878rbrbmwr.fsf@localhost> <83fs5zecpo.fsf@gnu.org> <87351zbi72.fsf@localhost> <83351yevde.fsf@gnu.org> <87cz12ad2w.fsf@localhost> <83a5w6cwdr.fsf@gnu.org> <87pm518m0g.fsf@localhost> <83o7kl9tyj.fsf@gnu.org> <874jmd89us.fsf@localhost> <83cz119lxu.fsf@gnu.org> <87v8et6q5m.fsf@localhost> Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="9341"; mail-complaints-to="usenet@ciao.gmane.io" Cc: monnier@iro.umontreal.ca, luangruo@yahoo.com, emacs-devel@gnu.org To: Ihor Radchenko Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Jul 09 18:36:22 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qIXOY-0002ES-0k for ged-emacs-devel@m.gmane-mx.org; Sun, 09 Jul 2023 18:36:22 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qIXNY-0006Uk-Ci; Sun, 09 Jul 2023 12:35:20 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qIXNV-0006UJ-Sp for emacs-devel@gnu.org; Sun, 09 Jul 2023 12:35:18 -0400 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qIXNU-0000Ih-RI; Sun, 09 Jul 2023 12:35:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=ThZOnrHVOjDjDqWgvhv8vQ3dk/6xepBYEJwtSE+y9QE=; b=eQ47b2dQrfDT tliEC1e+b/iVJ6LelLRHOjtxIcDAfe9oXixF94SvLo9gK3+d1GkzMH7M2Saxingkt+HtoSs+PejZ1 duH4/XX9dLOIIFKzqHWD2XNCfBJgSuZ6hF7b5FqBJ53afFCjFfrW6NwhlcKsW4ppkDPVBrG3+0Zt2 +39nQ0SI/+eOR8+3AIPxk4a7pJ0DFafJGkgw+6dPq3cPgRkQa94Yn//NOUt5gJh9Uod6wIpE66ST4 Hb2Zn/AX7hHicP2/L/NHNYFGpJZRdRfV/In8mopP8aE0pPAmxC+d+D5RxT7utqvaXBjoKPRFRvcEp yaZOtzeYnP9oFHF/6uUA5g==; Original-Received: from [87.69.77.57] (helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qIXNU-0001f5-Ao; Sun, 09 Jul 2023 12:35:16 -0400 In-Reply-To: <87v8et6q5m.fsf@localhost> (message from Ihor Radchenko on Sun, 09 Jul 2023 15:49:41 +0000) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:307694 Archived-At: > From: Ihor Radchenko > Cc: Stefan Monnier , luangruo@yahoo.com, > emacs-devel@gnu.org > Date: Sun, 09 Jul 2023 15:49:41 +0000 > > Eli Zaretskii writes: > > > ... then the buffer-local variables of that buffer present the same > > problem as global variables. Take the case-table or display-table, > > for example: those are buffer-local in many cases, but their changes > > will affect all the threads that work on the buffer. > > And how frequently are case-table and display-table changed? AFAIK, not > frequently at all. Why does it matter? Would you disallow programs doing that just because you think it's infrequent? Processing of various protocols frequently requires to do stuff like (with-case-table ascii-case-table DO SOMETHING...) because otherwise some locales, such as the Turkish one, cause trouble with case conversion of the upper-case 'I'. So changing the case-table of a buffer is not such an outlandish operation to do. > >> We need to ensure that simultaneous consing will never happen. AFAIU, > >> it should be ok if something that does not involve consing is running > >> at the same time with cons (correct me if I am wrong here). > > > > What do you do if some thread hits the memory-full condition? The > > current handling includes GC. > > May you please explain a bit more about the situation you are referring > to? My above statement was about consing, not GC. Consing can trigger GC if we detect the memory-full situation, see alloc.c:memory_full. > For GC, as I mentioned earlier, we can pause each thread once maybe_gc() > determines that GC is necessary, until all the threads are paused. Then, > GC is executed and the threads continue. If all the threads are paused, which thread will run GC? > If an async thread want to request redisplay, it should be possible. But > the redisplay itself must not be done by this same thread. Instead, the > thread will send a request that Emacs needs redisplay and optionally > block until that redisplay finishes (optionally, because something like > displaying notification may not require waiting). The redisplay requests > will be processed separately. Ouch! this again kills opportunities for gains from concurrent processing. It means, for example, that we will be unable to run in a thread some processing that affects a window and reflect that processing on display when it's ready. > Is Emacs display code even capable of redisplaying two different windows > at the same time? Maybe. At least the GUI redisplay proceeds one window at a time, so we already deal with each window separately. There are some caveats, naturally: redisplay runs hooks, which could access other windows, redisplaying a window also updates the frame title, etc. -- those will need to be carefully examined. > > Also, that issue with prompting the user also needs some solution, > > otherwise the class of jobs that non-main threads can do will be even > > smaller. > > We can make reading input using similar idea to the above, but it will > always block until the response. This will have to be designed and implemented first, since we currently have no provision for multiple prompt sources. > For non-blocking input, you said that it has been discussed. > I do vaguely recall such discussion in the past and I even recall some > ideas about it, but it would be better if you can link to that > discussion, so that the participants of this thread can review the > previously proposed ideas. https://lists.gnu.org/archive/html/emacs-devel/2018-08/msg00456.html > >> Only a single `main-thread' should be allowed to modify frames, > >> window configurations, and generally trigger redisplay. And thread > >> that attempts to do such modifications must wait to become > >> `main-thread' first. > > > > What about changes to frame-parameters? Those don't necessarily > > affect display. > > But doesn't it depend on graphic toolkit? Not necessarily: frame parameters are also used for "frame-local" variables, and those have nothing to do with GUI toolkits. > >> This means that any code that is using things like > >> `save-window-excursion', `display-buffer', and other display-related > >> staff cannot run asynchronously. > > > > What about with-selected-window? also forbidden? > > Yes. Too bad. > In addition, `with-selected-window' triggers redisplay. In particular, > it triggers redisplaying mode-lines. No, with-selected-window doesn't do any redisplay, it only marks the window for redisplay, i.e. it suppresses the redisplay optimization which could decide that this window doesn't need to be redrawn. Redisplay itself will happen normally, usually when Emacs is idle, i.e. when the command which called with-selected-window finishes. > >> Async threads will make an assumption that > >> (set-buffer "1") (goto-char 100) (set-buffer "2") (set-buffer "1") > >> (= (point) 100) invalid. > > > > If this is invalid, I don't see how one can write useful Lisp > > programs, except of we request Lisp to explicitly define critical > > sections. > > Hmm. I realized that it is already invalid. At least, if `thread-yield' > is triggered somewhere between `set-buffer' calls and other thread > happens to move point in buffer "1". But the programmer is in control! If no such API is called, point stays put. And if such APIs are called, the program can save and restore point around the calls. By contrast, you want to be able to pause and resume threads at will, which means a thread can be suspended at any time. So in this case, the programmer will be unable to do anything against such calamities. > >> > What if the main thread modifies buffer text, while one of the other > >> > threads wants to read from it? > >> > >> Reading and writing should be blocked while buffer is being modified. > > > > This will basically mean many/most threads will be blocked most of the > > time. Lisp programs in Emacs read and write buffers a lot, and the > > notion of forcing a thread to work only on its own single set of > > buffers is quite a restriction, IMO. > > But not the same buffers! I don't see why not. > To be clear, I do know how this function is designed to work. > It may not be de-facto pure, but that's just because nobody tried to > ensure it - the usefulness of pure declarations is questionable in Emacs > now. But that's the case with most Emacs Lisp programs: we rarely try too hard to make functions pure even if they can be pure. What's more important, most useful programs cannot be pure at all, because Emacs is about text processing, which means modifying text, and good Emacs Lisp programs process text in buffers, instead of returning strings, which makes them not pure. > >> There will indeed be a lot of work to make the range of Lisp functions > >> available for async code large enough. But it does not have to be done > >> all at once. > > > > No, it doesn't. But until we have enough of those functions > > available, one will be unable to write applications without > > implementing and debugging a lot of those new functions as part of the > > job. It will make simple programming jobs much larger and more > > complicated, especially since it will require the programmers to > > understand very well the limitations and requirements of concurrent > > code programming, something Lisp programmers don't know very well, and > > rightfully so. > > I disagree. So let's agree to disagree. Because I don't see how it will benefit anything to continue this dispute. I've said everything I have to say, sometimes more than once. At least Po Lu seems to agree that concurrent Emacs means we will have to write a lot of new routines, and that code which is meant to run in non-main threads will have to be written very specially.