1
+ #[ cfg( any( feature = "exec_embassy" ) ) ]
2
+ pub ( crate ) mod core_exec {
3
+ //! This module provides an abstraction layer for threading solutions, allowing for easier
4
+ //! swapping of threading implementations in the future.
5
+ //!
6
+ //! The module leverages the `embassy_executor` library for asynchronous execution and provides
7
+ //! utilities for initialization, spawning detached tasks, and blocking on futures.
8
+
9
+ use std:: future:: Future ;
10
+ use std:: io:: { self , Result } ;
11
+ use lazy_static:: lazy_static;
12
+ use parking_lot:: Once ;
13
+ use crate :: ProactorConfig ;
14
+ use embassy_executor:: { Executor , Spawner } ;
15
+
16
+ /// Spawns a local task intended for lightweight operations.
17
+ ///
18
+ /// In Embassy, tasks are scheduled on the executor without distinguishing between
19
+ /// local and pooled tasks. The task must be `'static` and produce a `'static` output.
20
+ pub fn spawn_local < F , T > ( f : F ) -> embassy_executor:: Task < T >
21
+ where
22
+ F : Future < Output = T > + ' static ,
23
+ T : ' static ,
24
+ {
25
+ let spawner = embassy_executor:: Spawner :: for_current_executor ( ) ;
26
+ spawner. spawn ( f)
27
+ }
28
+
29
+ /// Spawns a blocking task on a separate thread for CPU-bound or blocking operations.
30
+ ///
31
+ /// Embassy does not natively support blocking operations. This implementation simulates
32
+ /// blocking by running the closure in an async task, which may not be ideal for CPU-bound work.
33
+ pub fn spawn_blocking < F , T > ( f : F ) -> embassy_executor:: Task < T >
34
+ where
35
+ F : FnOnce ( ) -> T + Send + ' static ,
36
+ T : Send + ' static ,
37
+ {
38
+ let spawner = embassy_executor:: Spawner :: for_current_executor ( ) ;
39
+ spawner. spawn ( async move { f ( ) } )
40
+ }
41
+
42
+ /// Spawns a task that can run on any thread in the pool for parallel execution.
43
+ ///
44
+ /// In Embassy, this is identical to `spawn_local` as there’s no thread pool distinction.
45
+ pub fn spawn < F , T > ( future : F ) -> embassy_executor:: Task < T >
46
+ where
47
+ F : Future < Output = T > + Send + ' static ,
48
+ T : Send + ' static ,
49
+ {
50
+ let spawner = embassy_executor:: Spawner :: for_current_executor ( ) ;
51
+ spawner. spawn ( future)
52
+ }
53
+
54
+ /// Asynchronously spawns additional threads in the executor.
55
+ ///
56
+ /// Embassy does not support dynamic thread spawning, so this function returns an error.
57
+ pub async fn spawn_more_threads ( _count : usize ) -> io:: Result < usize > {
58
+ Err ( io:: Error :: new (
59
+ io:: ErrorKind :: Other ,
60
+ "Dynamic thread spawning not supported in Embassy" ,
61
+ ) )
62
+ }
63
+
64
+ lazy_static ! {
65
+ /// Ensures initialization runs only once across all threads.
66
+ static ref INIT : Once = Once :: new( ) ;
67
+ }
68
+
69
+ /// Initializes the Embassy executor with the specified configuration.
70
+ ///
71
+ /// If `enable_driver` is true, starts the executor in a dedicated thread.
72
+ /// The `proactor_config` and `queue_length` parameters are ignored as Embassy does not use
73
+ /// `io_uring` or similar configurable proactors.
74
+ pub ( crate ) fn init ( enable_driver : bool , _proactor_config : ProactorConfig , _queue_length : u32 ) {
75
+ INIT . call_once ( || {
76
+ if enable_driver {
77
+ trace ! ( "Starting Embassy driver" ) ;
78
+ std:: thread:: spawn ( || {
79
+ let executor = Executor :: new ( ) ;
80
+ executor. run ( |_spawner| {
81
+ // Embassy's executor runs indefinitely; no tasks are spawned here
82
+ // as the spawner is typically used elsewhere in the application.
83
+ } ) ;
84
+ } ) ;
85
+ }
86
+ } ) ;
87
+ }
88
+
89
+ /// Blocks the current thread until the given future completes.
90
+ ///
91
+ /// Embassy is not designed for blocking on a single future. This implementation runs
92
+ /// a new executor instance until the future completes, which may be inefficient.
93
+ pub fn block_on < F , T > ( future : F ) -> T
94
+ where
95
+ F : Future < Output = T > ,
96
+ T : ' static ,
97
+ {
98
+ let mut result = None ;
99
+ let executor = Executor :: new ( ) ;
100
+ executor. run ( |spawner| {
101
+ spawner. spawn ( async {
102
+ result = Some ( future. await ) ;
103
+ } )
104
+ } ) ;
105
+ result. expect ( "Future did not complete" )
106
+ }
107
+ }
0 commit comments