From 9d38e6c9622f6da60b738063840701017dc60681 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 30 Jun 2026 00:02:34 +0200 Subject: [PATCH] Share one MutexProtector between settings and the bookmark list BookmarkManager carried a byte-for-byte copy of ILSpySettings' private MutexProtector, both guarding read-modify-write of a config sidecar in the same settings directory so parallel ILSpy instances fold their edits in turn instead of clobbering each other. Promote it to a single public type in ICSharpCode.ILSpyX.Settings so the locking semantics live in one place. Assisted-by: Claude:claude-opus-4-8:Claude Code --- ICSharpCode.ILSpyX/Settings/ILSpySettings.cs | 30 ---------- ICSharpCode.ILSpyX/Settings/MutexProtector.cs | 55 +++++++++++++++++++ ILSpy/Bookmarks/BookmarkManager.cs | 28 +--------- 3 files changed, 56 insertions(+), 57 deletions(-) create mode 100644 ICSharpCode.ILSpyX/Settings/MutexProtector.cs diff --git a/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs b/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs index 4abb404f3..fad106dc4 100644 --- a/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs +++ b/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs @@ -18,7 +18,6 @@ using System; using System.IO; -using System.Threading; using System.Xml; using System.Xml.Linq; @@ -129,34 +128,5 @@ namespace ICSharpCode.ILSpyX.Settings } const string ConfigFileMutex = "01A91708-49D1-410D-B8EB-4DE2662B3971"; - - /// - /// Helper class for serializing access to the config file when multiple ILSpy instances are running. - /// - sealed class MutexProtector : IDisposable - { - readonly Mutex mutex; - - public MutexProtector(string name) - { - this.mutex = new Mutex(true, name, out bool createdNew); - if (createdNew) - return; - - try - { - mutex.WaitOne(); - } - catch (AbandonedMutexException) - { - } - } - - public void Dispose() - { - mutex.ReleaseMutex(); - mutex.Dispose(); - } - } } } diff --git a/ICSharpCode.ILSpyX/Settings/MutexProtector.cs b/ICSharpCode.ILSpyX/Settings/MutexProtector.cs new file mode 100644 index 000000000..2ca7aa760 --- /dev/null +++ b/ICSharpCode.ILSpyX/Settings/MutexProtector.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Threading; + +namespace ICSharpCode.ILSpyX.Settings +{ + /// + /// Guards a config-file read-modify-write with a named so that two ILSpy + /// instances editing the same sidecar (the settings XML, the bookmark list, ...) fold their + /// changes in turn instead of overwriting each other. Acquire it around the + /// read-update-write block and dispose it to release. + /// + public sealed class MutexProtector : IDisposable + { + readonly Mutex mutex; + + public MutexProtector(string name) + { + this.mutex = new Mutex(true, name, out bool createdNew); + if (createdNew) + return; + + try + { + mutex.WaitOne(); + } + catch (AbandonedMutexException) + { + } + } + + public void Dispose() + { + mutex.ReleaseMutex(); + mutex.Dispose(); + } + } +} diff --git a/ILSpy/Bookmarks/BookmarkManager.cs b/ILSpy/Bookmarks/BookmarkManager.cs index aff5d7558..cd7786fbc 100644 --- a/ILSpy/Bookmarks/BookmarkManager.cs +++ b/ILSpy/Bookmarks/BookmarkManager.cs @@ -27,9 +27,9 @@ using System.IO; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; -using System.Threading; using ICSharpCode.ILSpy.AppEnv; +using ICSharpCode.ILSpyX.Settings; namespace ICSharpCode.ILSpy.Bookmarks { @@ -361,31 +361,5 @@ namespace ICSharpCode.ILSpy.Bookmarks ViewState = ViewState, }; } - - sealed class MutexProtector : IDisposable - { - readonly Mutex mutex; - - public MutexProtector(string name) - { - mutex = new Mutex(true, name, out bool createdNew); - if (createdNew) - return; - - try - { - mutex.WaitOne(); - } - catch (AbandonedMutexException) - { - } - } - - public void Dispose() - { - mutex.ReleaseMutex(); - mutex.Dispose(); - } - } } }