11use anyhow:: { anyhow, Context as _, Result } ;
2+ use async_dispatcher:: { set_dispatcher, Dispatcher , Runnable } ;
23use collections:: { HashMap , HashSet } ;
34use editor:: {
45 display_map:: {
@@ -18,10 +19,11 @@ use outputs::{ExecutionStatus, ExecutionView, LineHeight as _};
1819use project:: Fs ;
1920use runtimelib:: JupyterMessageContent ;
2021use settings:: Settings as _;
21- use std:: ops:: Range ;
22- use std:: sync:: Arc ;
22+ use std:: { ops:: Range , sync :: mpsc :: RecvTimeoutError , time :: Instant } ;
23+ use std:: { sync:: Arc , time :: Duration } ;
2324use theme:: { ActiveTheme , ThemeSettings } ;
2425use ui:: prelude:: * ;
26+ use util:: ResultExt ;
2527use workspace:: Workspace ;
2628
2729mod outputs;
@@ -37,7 +39,79 @@ pub struct RuntimeManagerGlobal(Model<RuntimeManager>);
3739
3840impl Global for RuntimeManagerGlobal { }
3941
42+ pub fn zed_dispatcher ( cx : & mut AppContext ) -> impl Dispatcher {
43+ struct ZedDispatcher {
44+ tx : std:: sync:: mpsc:: Sender < ( Runnable , Option < Instant > ) > ,
45+ task : Task < ( ) > ,
46+ }
47+
48+ let ( tx, rx) = std:: sync:: mpsc:: channel ( ) ;
49+
50+ impl Dispatcher for ZedDispatcher {
51+ fn dispatch ( & self , runnable : async_dispatcher:: Runnable ) {
52+ self . tx . send ( ( runnable, None ) ) . log_err ( ) ;
53+ }
54+
55+ fn dispatch_after (
56+ & self ,
57+ duration : std:: time:: Duration ,
58+ runnable : async_dispatcher:: Runnable ,
59+ ) {
60+ self . tx
61+ . send ( ( runnable, Some ( Instant :: now ( ) + duration) ) )
62+ . log_err ( ) ;
63+ }
64+ }
65+
66+ let executor = cx. background_executor ( ) ;
67+
68+ let task = executor. spawn ( async {
69+ let mut timers = Vec :: < ( Runnable , Instant ) > :: new ( ) ;
70+ let rx = rx;
71+
72+ loop {
73+ let timeout = timers
74+ . first ( )
75+ . map ( |& ( _, time) | time. saturating_duration_since ( Instant :: now ( ) ) )
76+ . unwrap_or_else ( || Duration :: from_secs ( u64:: MAX ) ) ;
77+
78+ match rx. recv_timeout ( timeout) {
79+ Ok ( ( runnable, deadline) ) => {
80+ if let Some ( deadline) = deadline {
81+ let now = Instant :: now ( ) ;
82+ if deadline > now {
83+ let idx =
84+ match timers. binary_search_by_key ( & deadline, |& ( _, time) | time) {
85+ Ok ( i) => i,
86+ Err ( i) => i,
87+ } ;
88+ timers. insert ( idx, ( runnable, deadline) ) ;
89+ continue ;
90+ }
91+ }
92+ runnable. run ( ) ;
93+ }
94+
95+ Err ( RecvTimeoutError :: Timeout ) => {
96+ let now = Instant :: now ( ) ;
97+ while let Some ( ( _, deadline) ) = timers. first ( ) {
98+ if * deadline > now {
99+ break ;
100+ }
101+ timers. remove ( 0 ) . 0 . run ( ) ;
102+ }
103+ }
104+ Err ( RecvTimeoutError :: Disconnected ) => break ,
105+ }
106+ }
107+ } ) ;
108+
109+ ZedDispatcher { tx, task }
110+ }
111+
40112pub fn init ( fs : Arc < dyn Fs > , cx : & mut AppContext ) {
113+ set_dispatcher ( zed_dispatcher ( cx) ) ;
114+
41115 let runtime_manager = cx. new_model ( |cx| RuntimeManager :: new ( fs. clone ( ) , cx) ) ;
42116 RuntimeManager :: set_global ( runtime_manager. clone ( ) , cx) ;
43117
0 commit comments