@@ -53,7 +53,6 @@ use crossbeam::channel::bounded;
53
53
use crossbeam:: channel:: unbounded;
54
54
use crossbeam:: channel:: Receiver ;
55
55
use crossbeam:: channel:: Sender ;
56
- use crossbeam:: select;
57
56
use harp:: command:: r_command;
58
57
use harp:: command:: r_home_setup;
59
58
use harp:: environment:: r_ns_env;
@@ -103,6 +102,7 @@ use crate::lsp::main_loop::KernelNotification;
103
102
use crate :: lsp:: main_loop:: TokioUnboundedSender ;
104
103
use crate :: lsp:: state_handlers:: ConsoleInputs ;
105
104
use crate :: modules;
105
+ use crate :: modules:: ARK_ENVS ;
106
106
use crate :: plots:: graphics_device;
107
107
use crate :: r_task;
108
108
use crate :: r_task:: BoxFuture ;
@@ -443,7 +443,7 @@ impl RMain {
443
443
}
444
444
445
445
// Register all hooks once all modules have been imported
446
- let hook_result = RFunction :: from ( ".ps.register_all_hooks " ) . call ( ) ;
446
+ let hook_result = RFunction :: from ( "register_hooks " ) . call_in ( ARK_ENVS . positron_ns ) ;
447
447
if let Err ( err) = hook_result {
448
448
log:: error!( "Error registering some hooks: {err:?}" ) ;
449
449
}
@@ -753,6 +753,32 @@ impl RMain {
753
753
}
754
754
}
755
755
756
+ let mut select = crossbeam:: channel:: Select :: new ( ) ;
757
+
758
+ // Cloning is necessary to avoid a double mutable borrow error
759
+ let r_request_rx = self . r_request_rx . clone ( ) ;
760
+ let stdin_reply_rx = self . stdin_reply_rx . clone ( ) ;
761
+ let kernel_request_rx = self . kernel_request_rx . clone ( ) ;
762
+ let tasks_interrupt_rx = self . tasks_interrupt_rx . clone ( ) ;
763
+ let tasks_idle_rx = self . tasks_idle_rx . clone ( ) ;
764
+
765
+ let r_request_index = select. recv ( & r_request_rx) ;
766
+ let stdin_reply_index = select. recv ( & stdin_reply_rx) ;
767
+ let kernel_request_index = select. recv ( & kernel_request_rx) ;
768
+ let tasks_interrupt_index = select. recv ( & tasks_interrupt_rx) ;
769
+
770
+ // Don't process idle tasks in browser prompts. We currently don't want
771
+ // idle tasks (e.g. for srcref generation) to run when the call stack is
772
+ // empty. We could make this configurable though if needed, i.e. some
773
+ // idle tasks would be able to run in the browser. Those should be sent
774
+ // to a dedicated channel that would always be included in the set of
775
+ // recv channels.
776
+ let tasks_idle_index = if info. browser {
777
+ None
778
+ } else {
779
+ Some ( select. recv ( & tasks_idle_rx) )
780
+ } ;
781
+
756
782
loop {
757
783
// If an interrupt was signaled and we are in a user
758
784
// request prompt, e.g. `readline()`, we need to propagate
@@ -777,17 +803,31 @@ impl RMain {
777
803
// to be handled in a blocking way to ensure subscribers are
778
804
// notified before the next incoming message is processed.
779
805
780
- // First handle execute requests outside of `select! ` to ensure they
781
- // have priority. `select! ` chooses at random.
782
- if let Ok ( req) = self . r_request_rx . try_recv ( ) {
806
+ // First handle execute requests outside of `select` to ensure they
807
+ // have priority. `select` chooses at random.
808
+ if let Ok ( req) = r_request_rx. try_recv ( ) {
783
809
if let Some ( input) = self . handle_execute_request ( req, & info, buf, buflen) {
784
810
return input;
785
811
}
786
812
}
787
813
788
- select ! {
789
- // Wait for an execution request from the frontend.
790
- recv( self . r_request_rx) -> req => {
814
+ let oper = select. select_timeout ( Duration :: from_millis ( 200 ) ) ;
815
+
816
+ let Ok ( oper) = oper else {
817
+ // We hit a timeout. Process events because we need to
818
+ // pump the event loop while waiting for console input.
819
+ //
820
+ // Alternatively, we could try to figure out the file
821
+ // descriptors that R has open and select() on those for
822
+ // available data?
823
+ unsafe { Self :: process_events ( ) } ;
824
+ continue ;
825
+ } ;
826
+
827
+ match oper. index ( ) {
828
+ // We've got an execute request from the frontend
829
+ i if i == r_request_index => {
830
+ let req = oper. recv ( & r_request_rx) ;
791
831
let Ok ( req) = req else {
792
832
// The channel is disconnected and empty
793
833
return ConsoleResult :: Disconnected ;
@@ -796,35 +836,33 @@ impl RMain {
796
836
if let Some ( input) = self . handle_execute_request ( req, & info, buf, buflen) {
797
837
return input;
798
838
}
799
- }
839
+ } ,
800
840
801
841
// We've got a reply for readline
802
- recv( self . stdin_reply_rx) -> reply => {
803
- return self . handle_input_reply( reply. unwrap( ) , buf, buflen) ;
804
- }
842
+ i if i == stdin_reply_index => {
843
+ let reply = oper. recv ( & stdin_reply_rx) . unwrap ( ) ;
844
+ return self . handle_input_reply ( reply, buf, buflen) ;
845
+ } ,
805
846
806
847
// We've got a kernel request
807
- recv( self . kernel_request_rx) -> req => {
808
- self . handle_kernel_request( req. unwrap( ) , & info) ;
809
- }
848
+ i if i == kernel_request_index => {
849
+ let req = oper. recv ( & kernel_request_rx) . unwrap ( ) ;
850
+ self . handle_kernel_request ( req, & info) ;
851
+ } ,
810
852
811
- // A task woke us up, start next loop tick to yield to it
812
- recv( self . tasks_interrupt_rx) -> task => {
813
- self . handle_task_interrupt( task. unwrap( ) ) ;
814
- }
815
- recv( self . tasks_idle_rx) -> task => {
816
- self . handle_task( task. unwrap( ) ) ;
817
- }
853
+ // An interrupt task woke us up
854
+ i if i == tasks_interrupt_index => {
855
+ let task = oper. recv ( & tasks_interrupt_rx) . unwrap ( ) ;
856
+ self . handle_task_interrupt ( task) ;
857
+ } ,
818
858
819
- // Wait with a timeout. Necessary because we need to
820
- // pump the event loop while waiting for console input.
821
- //
822
- // Alternatively, we could try to figure out the file
823
- // descriptors that R has open and select() on those for
824
- // available data?
825
- default ( Duration :: from_millis( 200 ) ) => {
826
- unsafe { Self :: process_events( ) } ;
827
- }
859
+ // An idle task woke us up
860
+ i if Some ( i) == tasks_idle_index => {
861
+ let task = oper. recv ( & tasks_idle_rx) . unwrap ( ) ;
862
+ self . handle_task ( task) ;
863
+ } ,
864
+
865
+ i => log:: error!( "Unexpected index in Select: {i}" ) ,
828
866
}
829
867
}
830
868
}
@@ -2056,7 +2094,10 @@ fn do_resource_namespaces() -> bool {
2056
2094
let opt: Option < bool > = r_null_or_try_into ( harp:: get_option ( "ark.resource_namespaces" ) )
2057
2095
. ok ( )
2058
2096
. flatten ( ) ;
2059
- opt. unwrap_or ( true )
2097
+
2098
+ // By default we don't eagerly resource namespaces to avoid increased memory usage.
2099
+ // https://github.com/posit-dev/positron/issues/5050
2100
+ opt. unwrap_or ( false )
2060
2101
}
2061
2102
2062
2103
/// Are we auto-printing?
0 commit comments