Several Sucrose processes must run as a single instance — you should never have two tray icons, two settings windows, or two background services fighting over the same state. Sucrose enforces this with named Windows mutexes through a deliberately strict gate, Instance.Basic, that requires both a freshly-created mutex and a process-count check. This page documents the gate, the full mutex-name table, which processes gate versus which are intentionally re-runnable, and what happens on a double launch.
Instance.Basic ruleInstance.Single alternativeInstance.Basic ruleFile: src/Shared/Sucrose.Shared.Space/Helper/Instance.cs.
Instance.Basic(name, application):
Mutex(true, name, out createdNew).createdNew && Processor.WorkCount(application) <= 1 — i.e. the mutex must be newly created AND at most one process of that executable name may currently exist.false.This is a deliberately strict double-check: a fresh mutex alone is not enough — the process-count safeguard catches edge cases where a mutex was abandoned but a copy of the process is still alive.
Instance.Basic(name, application):
Mutex(true, name, out createdNew)
return createdNew && WorkCount(application) <= 1
Instance.Single alternativeAn alternate helper, Instance.Single(name, application), returns Skylark.Wing.Utility.SingleInstance.IsAppMutexRunning(name) && WorkCount(application) <= 1 — i.e. it pairs the Skylark.Wing mutex check with the same process-count safeguard used by Instance.Basic. Instance.Basic is the one used by the startup gates documented below.
Mutex names are well-known, brace-wrapped constants (session-local — no Global\ prefix, so each is created in the per-session namespace), defined in src/Library/Sucrose.Memory/Manage/Readonly/Mutex.cs.
| Process | Mutex name |
|---|---|
| Live engine (shared by all 7 engines) | {Sucrose-Wallpaper-Engine-Live} |
| Portal | {Sucrose-Wallpaper-Engine-Portal} |
| Update | {Sucrose-Wallpaper-Engine-Update} |
| Property | {Sucrose-Wallpaper-Engine-Property} |
| Launcher | {Sucrose-Wallpaper-Engine-Launcher} |
| Reportdog | {Sucrose-Wallpaper-Engine-Reportdog} |
| Backgroundog | {Sucrose-Wallpaper-Engine-Backgroundog} |
All eight live engines share the single {Sucrose-Wallpaper-Engine-Live} mutex concept — only one wallpaper render engine may be alive at a time.
Processes that gate on single-instance via Instance.Basic in their OnStartup / Main:
| Process | Gates with Instance.Basic? |
|---|---|
| Launcher | Yes |
| Portal | Yes |
| Update | Yes |
| Property | Yes |
| Backgroundog | Yes |
| Reportdog | Yes |
| Commandog | No — intentionally re-runnable short-lived broker |
| Watchdog | No — intentionally re-runnable short-lived crash handler |
| Undo | No |
| Live engines | Yes — each engine calls Instance.Basic(SMMRM.Live, SMMRA.<engine>Live) (the shared {Sucrose-Wallpaper-Engine-Live} mutex) ANDed with an extra SSEHR.Check() engine-readiness check, so only one render engine may be alive at a time |
Commandog and Watchdog must be re-runnable: many actions and many crashes can occur in quick succession, and each spawns a fresh short-lived broker/handler. Do not describe them as resident services.
If Instance.Basic returns false (an instance already exists), the process does not stay resident. Behavior differs by process:
SSLCI.Command() (open the Portal via ✔Interface✖<Portal>) and then Close()s itself.Close()s (no second window).Close()).The most user-visible consequence: double-launching the Launcher opens the settings window, it does not create a second tray icon. Because the second Launcher instance fails the gate and redirects through Commandog to open the Portal, the user gets the management UI rather than a duplicate tray presence. Likewise, asking to open the Portal while it is already running just focuses on the existing window instead of spawning a duplicate.