From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Ihor Radchenko Newsgroups: gmane.emacs.devel Subject: Re: Emacs design and architecture. How about copy-on-write? Date: Mon, 18 Sep 2023 12:49:21 +0000 Message-ID: <877conk5ny.fsf@localhost> References: <83edizjn0v.fsf@gnu.org> <0518f65b-1dd1-6923-8497-da4d3aeac631@gutov.dev> <87sf7fc7kd.fsf@dataswamp.org> <834jjuk68t.fsf@gnu.org> <87cyyhc7uu.fsf@dataswamp.org> <83ttrsg9nx.fsf@gnu.org> <83h6nrg4eg.fsf@gnu.org> <83v8c7elan.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="14392"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Alan Mackenzie , incal@dataswamp.org, emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Sep 18 14:49:17 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 1qiDgj-0003Yu-3K for ged-emacs-devel@m.gmane-mx.org; Mon, 18 Sep 2023 14:49:17 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qiDfn-0006kV-AJ; Mon, 18 Sep 2023 08:48:19 -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 1qiDfj-0006k1-9E for emacs-devel@gnu.org; Mon, 18 Sep 2023 08:48:15 -0400 Original-Received: from mout01.posteo.de ([185.67.36.65]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qiDfh-0002bJ-05 for emacs-devel@gnu.org; Mon, 18 Sep 2023 08:48:15 -0400 Original-Received: from submission (posteo.de [185.67.36.169]) by mout01.posteo.de (Postfix) with ESMTPS id 8C8A9240027 for ; Mon, 18 Sep 2023 14:48:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1695041286; bh=+ZkpsjlDh/tVgY87O3JMWFf+AnCln/bvEeRARXxoFK8=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:From; b=qHa9av8TNN+ifJN7jjIchnZjtD9oMw+8uF4eWug7EzWqkPiwyMAFDPZ9OBBiUNxSn XzvmYOr4iqbJWiwu2Z1y1PnNMaOzQEAVqnKyi8aAAJUtLuay6Z8kcHqEqoRR3TRza8 /Xb8G8U0IZWKTXrGkFqB61FcsOzlUoQfVzRmXIwSnTpGVPgfyLltJA/ngMC8c+jgfW XnYsEnr1HEcOyM0bT77gx1kPpGt5JbGmC+PtnHr2qNtjT9lq9kPr4W5E/VNcfj6SSv YKNeZ7QCyy0be9rB/ujvk+m81TEo17/v6zmS6xr6lw/zoghQk6A0NS0MsxFyz47Ny6 fZx+rSyZVPyng== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4Rq4Mn2nwzz9rxK; Mon, 18 Sep 2023 14:48:05 +0200 (CEST) In-Reply-To: <83v8c7elan.fsf@gnu.org> Received-SPF: pass client-ip=185.67.36.65; envelope-from=yantar92@posteo.net; helo=mout01.posteo.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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:310697 Archived-At: Eli Zaretskii writes: >> You mean that at the end of a thread, it will need to write results back >> to variables "owned" by the calling thread. Yes. Either these variables >> get marked as thread-global (not very attractive), or else we would need >> to mark specific variables as not to be copied on write. > > After the thread terminates, and perhaps also while it still runs. > E.g., consider some kind of progress-reporting facility. I think this can be approached similar to buffer-local values - all the symbols will have default value (global), and per-thread values. When threads set symbol value normally (for example, via setq), the per-thread value is modified (and possibly written back to "global" after the thread terminates). But thread might need to write "global" directly - something similar to `set-default-toplevel-value' might be used then. >> With a thread fetching Gnus articles, there is the additional >> complication of having several such threads fetching from several servers >> at once. Then access to the result variables would need to be locked, to >> prevent two threads overwriting eachother's results. But this is so in >> any multithreading system, no matter how it's done. > > The danger is indeed that most of the variables will need to be > protected by locks. If we cannot find a way of avoiding that, we are > back at the current "only one thread at a time" model, and there's > nothing to gain. I think that there is a limit to what can be done generically without affecting the existing Elisp code. Modifying a global variable asynchronously might need to be coded explicitly on Elisp level by more granular locks (to be provided as a part of async thread API). For example, if Gnus is collecting all the articles into a list of (("server1" . articles) ("server2" . articles)), only Gnus will know that it is enough to lock cdr of "server1" when fetching articles from server 1. In other scenarios, like modifying hash table, it might be possible to provide thread-safe implementations on C level. Those might or might not be good enough, depending on the use-case. >> I envisage each buffer being "owned" by a thread, possibly a special >> thread just controlling access to the buffer. Variables like >> scroll-margin would be the thread's own binding of it. There are a large >> number of dynamic variables in redisplay which, in the current Emacs, >> when bound by a thread would affect Emacs globally. This c-o-w proposal >> would fix this problem. > > I'm confused: suppose one thread modifies scroll-margin -- does that > affect the (global) redisplay? If it does, how will this "solve" the > problem? If it doesn't affect redisplay, how _can_ a thread change > scroll-margin in order to affect redisplay? IMHO, the only sane way to utilize the existing redisplay is redisplay lock - only one thread can request redisplay at a time, using its thread-local state. >> I don't think several redisplay threads would be a good idea - usually, >> there is just one screen Emacs is drawing on. > > It's one screen, but each window is redrawn separately (on GUI > terminals). Technically yes, but AFAIU the code is written assuming single-threaded execution. Decoupling redisplay of different windows would require significant non-trivial changes in xdisp.c >> The c-o-w idea could steer around at least part of the globality. I >> think it would be relatively simple to implement (hah!) and wouldn't have >> a large run-time cost, though of course there would be some. > > I think the copy-on-write idea will work only for thread-local > variables, and we already have those in the form of let-bindings. The > important (and the hard) part of this is elsewhere. Yup. For example, buffer-local symbols are implemented using forward pointers, overriding buffer object any time we alter (like let-bind) a buffer-local value. >From implementation perspective, it might be easier to extend symbol value slots of symbol object and buffer-local variable slots of buffer objects to store values for multiple threads + a default value. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at . Support Org development at , or support my work at