unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: David Ponce via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 72689@debbugs.gnu.org
Subject: bug#72689: 31.0.50; Proposal to improve string-pixel-width
Date: Thu, 22 Aug 2024 11:48:48 +0200	[thread overview]
Message-ID: <c5045744-ba54-4715-b288-992909193697@orange.fr> (raw)
In-Reply-To: <86seuxte6r.fsf@gnu.org>

On 22/08/2024 5:43 AM, Eli Zaretskii wrote:
>> Date: Wed, 21 Aug 2024 22:43:08 +0200
>> Cc: 72689@debbugs.gnu.org
>> From: David Ponce <da_vid@orange.fr>
>>
>> On 21/08/2024 3:17 PM, Eli Zaretskii wrote:
>>> Thanks, but using a mutex is overkill: there could be no race between
>>> two or more threads in this case in accessing the buffer-local
>>> variable, because only one Lisp thread can be running at any given
>>> time.  So the simpler method of testing the "busy" flag should be
>>> sufficient.
>>
>> I used a mutex to protect the global variable `work-buffer--list'
>> (which holds the list buffers available to be reused) against
>> concurrent accesses during the very simple update operations: pop an
>> available buffer, push a released buffer to make it available.
>>
>> Of course, if you guarantee that only one Lisp thread can be running
>> at any given time, protecting `work-buffer--list' against concurrent
>> accesses is not necessary and mutex can be removed.
> 
> Yes, I think so.
> 
>> Here is the new version without mutex (no significant impact on
>> performance compared to the version with mutex):
> 
> Thanks, LGTM.
> 
>> Should I prepare a patch of subr-x.el to include both the proposed
>> `work-buffer' API, and an implementation of `string-pixel-width' using
>> it?
> 
> Yes, please.  And the macro itself needs a NEWS entry, I think.

Thanks.  I will prepare a patch and a NEWS entry for the new
`with-work-buffer' macro ASAP.

Could you please review this last version of the work-buffer API,
which introduce the variable `work-buffer-limit' to limit the number
of work buffers?

Such a limit minimizes the risk of keeping a large number of work
buffers throughout the entire Emacs session when, for example,
`with-work-buffer' is called recursively, as illustrated by this very
poorly written function:

;; Example of a poorly written function that could produce a big number
;; of work buffers!
(defun bad-make-string (char &optional count)
   (or (natnump count) (setq count 0))
   (with-work-buffer
     (insert-char char)
     (if (> count 1)
         (insert (bad-make-string char (1- count))))
     (buffer-string)))

For now, `work-buffer-limit' is a simple variable that can be
let-bound to temporarily increase the limit if needed.  I'm not sure a
customizable user option is useful.  The default limit of 10 can also
be changed if you think it is not enough or on the contrary is too
much.

Below is the new code.  The benchmarks result are still similar.

(defvar work-buffer--list nil)
(defvar work-buffer-limit 10
   "Maximum number of reusable work buffers.
When this limit is exceeded, newly allocated work buffers are
automatically killed, which means that in a such case
`with-work-buffer' becomes equivalent to `with-temp-buffer'.")

(defsubst work-buffer--get ()
   "Get a work buffer."
   (let ((buffer (pop work-buffer--list)))
     (if (buffer-live-p buffer)
         buffer
       (generate-new-buffer " *work*" t))))

(defun work-buffer--release (buffer)
   "Release work BUFFER."
   (if (buffer-live-p buffer)
       (with-current-buffer buffer
         ;; Flush BUFFER before making it available again, i.e. clear
         ;; its contents, remove all overlays and buffer-local
         ;; variables.  Is it enough to safely reuse the buffer?
         (erase-buffer)
         (delete-all-overlays)
         (let (change-major-mode-hook)
	  (kill-all-local-variables t))
         ;; Make the buffer available again.
         (push buffer work-buffer--list)))
   ;; If the maximum number of reusable work buffers is exceeded, kill
   ;; work buffer in excess, taking into account that the limit could
   ;; have been let-bound to temporarily increase its value.
   (when (> (length work-buffer--list) work-buffer-limit)
     (mapc #'kill-buffer (nthcdr work-buffer-limit work-buffer--list))
     (setq work-buffer--list (ntake work-buffer-limit work-buffer--list))))

;;;###autoload
(defmacro with-work-buffer (&rest body)
   "Create a work buffer, and evaluate BODY there like `progn'.
Like `with-temp-buffer', but reuse an already created temporary
buffer when possible, instead of creating a new one on each call."
   (declare (indent 0) (debug t))
   (let ((work-buffer (make-symbol "work-buffer")))
     `(let ((,work-buffer (work-buffer--get)))
        (with-current-buffer ,work-buffer
          (unwind-protect
	     (progn ,@body)
            (work-buffer--release ,work-buffer))))))






  reply	other threads:[~2024-08-22  9:48 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-17 22:03 bug#72689: 31.0.50; Proposal to improve string-pixel-width David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-18  4:40 ` Eli Zaretskii
2024-08-18  6:05   ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-18  9:15     ` Eli Zaretskii
2024-08-19  8:49       ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-20 15:12       ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-21 13:17         ` Eli Zaretskii
2024-08-21 20:43           ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-22  3:43             ` Eli Zaretskii
2024-08-22  9:48               ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2024-08-22 10:59                 ` Eli Zaretskii
2024-08-22 14:56                   ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-23  6:20                     ` Juri Linkov
2024-08-23  6:49                       ` Eli Zaretskii
2024-08-23  7:23                         ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-31  8:26                     ` Eli Zaretskii
2024-08-31 10:51                       ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-31 12:00                         ` Eli Zaretskii
2024-08-18  6:12 ` Jim Porter
2024-08-18  7:36   ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-18 16:35     ` Jim Porter
2024-08-18  9:23   ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c5045744-ba54-4715-b288-992909193697@orange.fr \
    --to=bug-gnu-emacs@gnu.org \
    --cc=72689@debbugs.gnu.org \
    --cc=da_vid@orange.fr \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).