Update scheduler integration plan with Phase 2 investigation notes

Attempted to delegate GPUI's block_internal to scheduler.block() but
encountered an issue with the blocked_sessions mechanism interfering
with user code calling tick() from within a blocked future.

Updated the plan to document this finding and possible solutions to
investigate. The current workaround (GPUI using tick() directly) works
but is not the final desired state.
This commit is contained in:
Nathan Sobo
2025-12-14 07:46:31 -07:00
parent a788c91de9
commit fc620bba43

View File

@@ -113,19 +113,25 @@ Created `SharedRng` wrapper type that handles locking internally:
- `SharedRng::lock()` - for cases needing `&mut Rng` (e.g., `slice::choose()`)
- Updated `TestScheduler::rng()` and `BackgroundExecutor::rng()` to return `SharedRng`
### Phase 2: Move Unparkers to TestScheduler
### 🔶 Phase 2: Delegate block_internal to scheduler.block() (BLOCKED - needs investigation)
Move the unparker mechanism into TestScheduler to unify blocking between GPUI's `block_internal` and scheduler's `block`:
**Attempted:** Tried to have GPUI's `block_internal` delegate to `scheduler.block()` instead of maintaining its own polling loop.
```rust
impl TestScheduler {
pub fn push_unparker(&self, unparker: Unparker);
pub fn unpark_all(&self);
pub fn unparker_count(&self) -> usize;
}
```
**Problem:** The scheduler's `blocked_sessions` mechanism prevents foreground tasks from the blocked session from running during `step_filtered()` calls. This breaks tests that call `run_until_parked()` inside an async test:
Call `unpark_all()` when tasks are scheduled in `schedule_foreground()` and `schedule_background()`.
1. `block_test` calls `scheduler.block(session_id, future)`
2. Scheduler adds `session_id` to `blocked_sessions`
3. Inside the async test, `cx.executor().run_until_parked()` is called
4. `run_until_parked` calls `tick()``step_filtered()`
5. `step_filtered` skips tasks from blocked sessions
6. Foreground tasks for the test's session don't run → test fails
**Current workaround:** GPUI keeps its own `block_internal` implementation that uses `tick()` directly. This works because `tick()` doesn't involve the `blocked_sessions` mechanism - only the scheduler's internal `block()` does.
**Possible solutions to investigate:**
- Have the scheduler distinguish between "internal stepping during block()" vs "user-initiated tick()" and only apply `blocked_sessions` filtering to the former
- Temporarily remove session from `blocked_sessions` while polling the user's future, only blocking during internal step() calls
- Rethink the `blocked_sessions` mechanism entirely
### Phase 3: Move simulate_random_delay to TestScheduler
@@ -177,6 +183,12 @@ For production (Mac/Linux/Windows), either:
4. All existing tests pass
5. Minimal code in GPUI for test scheduling support
## Notes
- The `blocked_sessions` mechanism in TestScheduler is designed to prevent re-entrancy during the internal stepping of `block()`, but it currently interferes with user code that calls `tick()` from within a blocked future. This needs further investigation.
- GPUI's `block_internal` has complex requirements around parking, unparking, and timeout handling that need consideration when integrating with the scheduler's `block()` API.
- The current architecture where GPUI uses `tick()` directly in its polling loop works correctly and avoids the `blocked_sessions` issue, but is not the final desired state.
---
## Notes for Implementation