[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/undo-tree ffd18cd 175/195: Refactor undo-list-transfer-
From: |
Stefan Monnier |
Subject: |
[elpa] externals/undo-tree ffd18cd 175/195: Refactor undo-list-transfer-to-tree again in attempt to mitigate GC races. |
Date: |
Sat, 28 Nov 2020 13:41:47 -0500 (EST) |
branch: externals/undo-tree
commit ffd18cd6250467273815349b0a6c0e569e64ae3d
Author: Toby S. Cubitt <toby-undo-tree@dr-qubit.org>
Commit: Toby S. Cubitt <toby-undo-tree@dr-qubit.org>
Refactor undo-list-transfer-to-tree again in attempt to mitigate GC races.
Now undo-list-transfer-to-tree first garbage-collects to try to avoid GC of
buffer-undo-list during processing, then deep-copies buffer-undo-list and
operates on the copy to minimise window for GC races.
Not clear if GC races can cause undo history corruption, but mitigating the
chances seems worth a shot.
---
undo-tree.el | 37 +++++++++++++++++--------------------
1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/undo-tree.el b/undo-tree.el
index cbed590..6ae4f69 100644
--- a/undo-tree.el
+++ b/undo-tree.el
@@ -1754,7 +1754,7 @@ Comparison is done with `eq'."
copy)))
-(defun undo-list-transfer-to-tree (undo-list)
+(defun undo-list-transfer-to-tree ()
;; Transfer entries accumulated in `undo-list' to `buffer-undo-tree'.
;; `undo-list-transfer-to-tree' should never be called when undo is disabled
@@ -1764,7 +1764,13 @@ Comparison is done with `eq'."
;; if `buffer-undo-tree' is empty, create initial undo-tree
(when (null buffer-undo-tree) (setq buffer-undo-tree (make-undo-tree)))
- (let (changeset)
+ ;; garbage-collect then deep-copy `buffer-undo-list', in an attempt to
+ ;; mitigate race conditions with garbage collector corrupting undo history
+ ;; -- is this even a thing?
+ (garbage-collect)
+ (let ((undo-list (copy-tree buffer-undo-list))
+ changeset)
+ (setq buffer-undo-list '(nil undo-tree-canary))
(when (setq changeset (undo-list-pop-changeset undo-list))
;; create new node from first changeset in `undo-list', save old
;; `buffer-undo-tree' current node, and make new node the current node
@@ -1814,7 +1820,7 @@ Comparison is done with `eq'."
(defun undo-list-rebuild-from-tree ()
"Rebuild `buffer-undo-list' from information in `buffer-undo-tree'."
(unless (eq buffer-undo-list t)
- (undo-list-transfer-to-tree buffer-undo-list)
+ (undo-list-transfer-to-tree)
(setq buffer-undo-list nil)
(when buffer-undo-tree
(let ((stack (list (list (undo-tree-root buffer-undo-tree)))))
@@ -2758,8 +2764,7 @@ changes within the current region."
pos current)
;; transfer entries accumulated in `buffer-undo-list' to
;; `buffer-undo-tree'
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
(dotimes (_ (or (and (numberp arg) (prefix-numeric-value arg)) 1))
;; check if at top of undo tree
@@ -2868,8 +2873,7 @@ changes within the current region."
pos current)
;; transfer entries accumulated in `buffer-undo-list' to
;; `buffer-undo-tree'
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
(dotimes (_ (or (and (numberp arg) (prefix-numeric-value arg)) 1))
;; check if at bottom of undo tree
@@ -2951,9 +2955,7 @@ This will affect which branch to descend when *redoing*
changes
using `undo-tree-redo'."
(interactive (list (or (and prefix-arg (prefix-numeric-value prefix-arg))
(and (not (eq buffer-undo-list t))
- (or (undo-list-transfer-to-tree
- buffer-undo-list)
- (setq buffer-undo-list '(nil
undo-tree-canary)))
+ (undo-list-transfer-to-tree)
(let ((b (undo-tree-node-branch
(undo-tree-current
buffer-undo-tree))))
@@ -2977,8 +2979,7 @@ using `undo-tree-redo'."
(when (or (< branch 0) (> branch (1- (undo-tree-num-branches))))
(user-error "Invalid branch number"))
;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
;; switch branch
(setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
branch)
@@ -3031,8 +3032,7 @@ Argument is a character, naming the register."
(when (eq buffer-undo-list t)
(user-error "No undo information in this buffer"))
;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
;; save current node to REGISTER
(set-register
register (registerv-make
@@ -3063,8 +3063,7 @@ Argument is a character, naming the register."
((not (eq (current-buffer) (undo-tree-register-data-buffer data)))
(user-error "Register contains undo-tree state for a different buffer")))
;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
;; restore buffer state corresponding to saved node
(undo-tree-set (undo-tree-register-data-node data))))
@@ -3102,8 +3101,7 @@ without asking for confirmation."
(user-error "Undo-tree mode not enabled in buffer"))
(when (eq buffer-undo-list t)
(user-error "No undo information in this buffer"))
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
(when (and buffer-undo-tree (not (eq buffer-undo-tree t)))
(undo-tree-kill-visualizer)
;; should be cleared already by killing the visualize, but writes
@@ -3273,8 +3271,7 @@ signaling an error if file is not found."
(when (eq buffer-undo-list t)
(user-error "No undo information in this buffer"))
;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
- (undo-list-transfer-to-tree buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
+ (undo-list-transfer-to-tree)
;; add hook to kill visualizer buffer if original buffer is changed
(add-hook 'before-change-functions 'undo-tree-kill-visualizer nil t)
;; prepare *undo-tree* buffer, then draw tree in it
- [elpa] externals/undo-tree 965650c 127/195: Highlight node in visualizer corresponding to unmodified buffer., (continued)
- [elpa] externals/undo-tree 965650c 127/195: Highlight node in visualizer corresponding to unmodified buffer., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree ca9ec7b 105/195: Clear visualizer data / kill visualizer before saving history., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 270bc25 110/195: Added `~' to end of default history save-file name., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree d5a6148 120/195: Don't try to auto-save undo history if undo is disabled in buffer., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree cfc036a 133/195: Fix undo-tree-redo to avoid corrupting undo-tree state if redoing fails., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree bdfd73f 132/195: Ignore bogus buffer modification entries in undo changesets., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 6e0775d 139/195: Use define-derived-mode and define-minor-mode for undo-tree visualizer., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree d6fa2e7 152/195: Reinstate accidentally deleted file header., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 8afead1 162/195: Add Maintainer line to package headers., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree e9a9102 164/195: Throw error if interactive commands called outside undo-tree-mode., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree ffd18cd 175/195: Refactor undo-list-transfer-to-tree again in attempt to mitigate GC races.,
Stefan Monnier <=
- [elpa] externals/undo-tree 941bfe5 190/195: Don't attempt to save undo history if history file is unwritable., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 5a1ba84 017/195: Added standard Elisp package headers, including an extensive Commentary., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 62e6097 044/195: Added undo-tree-save/restore-state-to/from-register commands and keybindings, Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree c638cbd 051/195: General code tidying and reorganisation., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree caa3bd0 082/195: Added new customization option to allow undo-in-region to be disabled., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 8972e4d 069/195: Use get-buffer-create when creating the visualizer buffer in undo-tree-visualize., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree d7c1b2c 118/195: "De-circle" undo-tree when saving to file, restore when loading., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 121cab9 136/195: Trivial typo fixes in comments., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 18754c1 114/195: Use with-temp-buffer instead of with-temp-file when saving undo history., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree c9f78c3 137/195: Use new user-error instead of error for expected undo errors., Stefan Monnier, 2020/11/28