zed/crates/remote/src
Nathan Sobo c30d18b10d
scheduler: Add spawn_dedicated for single-threaded actors with !Send state (#57609)
Adds `scheduler::spawn_dedicated_thread` (and inherent `spawn_dedicated`
methods on `PlatformScheduler` and `TestScheduler`) so single-threaded
actors that own `!Send` state can run on their own OS thread and freely
do blocking I/O without disturbing any other executor.

### Why

A single-threaded actor that needs to do blocking syscalls is currently
stuck: it can't run on the shared foreground executor (blocking would
stall every other foreground session), and it can't move to the
background pool because its state isn't `Send`. `spawn_dedicated` gives
each such actor its own thread and its own `LocalExecutor`, while still
participating in the same testable scheduler infrastructure as
everything else.

### Shape

- `pub fn spawn_dedicated_thread(session_id, scheduler, f) -> Task<_>`
in `scheduler`. Owns the OS thread, the per-session runnable channel,
and the `LocalExecutor` setup.
- Inherent `spawn_dedicated` on `PlatformScheduler` (allocates its own
`SessionId`, delegates to the free function).
- Inherent `spawn_dedicated` on `TestScheduler` (no real thread — runs
as a fresh local session driven by the test scheduler's run loop, so
determinism under `many` is preserved).
- Renames `Scheduler::schedule_foreground` → `schedule_local` and
`scheduler::ForegroundExecutor` → `scheduler::LocalExecutor` to reflect
that these are session-pinned queues rather than "the main thread" (a
dedicated session runs on its own thread). GPUI's wrapper
`gpui::ForegroundExecutor` and the `foreground_executor` field/method
names are unchanged to keep blast radius small.
- `LocalExecutor::new` now takes an explicit dispatch closure, so the
routing decision (default session, dedicated thread, or something else)
lives at the construction site.

### Tests

- `TestScheduler` side: round-trip, `!Send` future, `Send` closure
capturing shared state, inner `executor.spawn`, determinism under `many`
seeds, drop-cancels-future, detached child runs after root completes.
- `PlatformScheduler` side: real separate thread (blocking syscalls
don't stall the test), `!Send` future output, drop-cancels-future,
thread tears down after work completes, detached child outlives root.

cc @as-cii

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2026-05-29 15:58:02 +00:00
..
transport Remove CRLF line endings (#57680) 2026-05-26 12:59:21 +00:00
json_log.rs remote: Add remote timeout debugging commands (#46695) 2026-01-13 13:39:07 +00:00
protocol.rs Restructure remote client crate, consolidate SSH logic (#36967) 2025-08-27 00:15:39 +00:00
proxy.rs remote: Fix being unable to reconnect when the remote server dies (#47200) 2026-01-20 10:44:29 +00:00
remote.rs sidebar: Filter thread groups by remote host identity (#53918) 2026-04-14 18:40:36 +00:00
remote_client.rs scheduler: Add spawn_dedicated for single-threaded actors with !Send state (#57609) 2026-05-29 15:58:02 +00:00
remote_identity.rs sidebar: Filter thread groups by remote host identity (#53918) 2026-04-14 18:40:36 +00:00
transport.rs remote: Set current_dir for cargo zigbuild cross-compilation (#53951) 2026-04-15 09:07:53 +00:00