1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Global executor management for program-wide task execution.
//!
//! This module provides functionality for setting and accessing a global executor
//! that persists for the entire lifetime of the program. This is useful when you
//! need to spawn tasks from contexts where you cannot easily pass an executor
//! as a parameter, such as signal handlers or global initialization code.
//!
//! # Overview
//!
//! The global executor pattern allows you to:
//! - Set a single executor for the entire program using [`set_global_executor`]
//! - Access this executor from anywhere using [`global_executor`]
//! - Spawn tasks without needing to thread an executor through your call stack
//!
//! # Important Considerations
//!
//! - The global executor can only be set once. Attempting to set it multiple times
//! will panic.
//! - You must initialize the global executor before attempting to use it. Accessing
//! an uninitialized global executor will return `None`.
//! - For most use cases, [`crate::current_executor::current_executor`] is preferred
//! as it provides more flexibility and context-aware executor selection.
//!
//! # Example Usage
//!
//! ```no_run
//! # // not runnable because we use `todo!()`
//! use some_executor::global_executor::{set_global_executor, global_executor};
//! use some_executor::DynExecutor;
//!
//! // Initialize the global executor early in your program
//! let executor: Box<DynExecutor> = todo!(); // Your executor implementation
//! set_global_executor(executor);
//!
//! // Later, from anywhere in your program
//! global_executor(|e| {
//! if let Some(executor) = e {
//! // Use the executor
//! let mut executor = executor.clone_box();
//! // spawn tasks...
//! }
//! });
//! ```
use crateDynExecutor;
use OnceLock;
static GLOBAL_RUNTIME: = new;
/// Accesses the global executor through a callback function.
///
/// This function provides safe access to the global executor (if one has been set)
/// through a callback pattern. The callback receives an `Option<&DynExecutor>` which
/// will be `Some` if a global executor has been initialized, or `None` otherwise.
///
/// # Arguments
///
/// * `c` - A closure that receives `Option<&DynExecutor>` and returns a value of type `R`
///
/// # Returns
///
/// Whatever value the callback function returns.
///
/// # Usage Patterns
///
/// ## Cloning the executor for task spawning
///
/// ```no_run
/// # // not runnable because there is no global executor set in this config
/// use some_executor::global_executor::global_executor;
/// use some_executor::task::{Task, ConfigurationBuilder};
///
/// let mut executor = global_executor(|e| {
/// e.expect("Global executor not initialized").clone_box()
/// });
///
/// // Now you can spawn tasks
/// let task = Task::without_notifications(
/// "my-task".to_string(),
/// ConfigurationBuilder::new().build(),
/// async { 42 },
/// );
/// # // executor.spawn(task);
/// ```
///
/// ## Checking if executor is available
///
/// ```
/// use some_executor::global_executor::global_executor;
///
/// let is_available = global_executor(|e| e.is_some());
/// if !is_available {
/// println!("Global executor not initialized");
/// }
/// ```
///
/// ## Spawning with fallback
///
/// ```
/// use some_executor::global_executor::global_executor;
/// use some_executor::current_executor::current_executor;
///
/// // Try global executor, fall back to current executor
/// let mut executor = global_executor(|e| {
/// e.map(|exec| exec.clone_box())
/// }).unwrap_or_else(|| current_executor());
/// ```
///
/// # Important Notes
///
/// - The global executor must be initialized with [`set_global_executor`] before use
/// - For most use cases, prefer [`crate::current_executor::current_executor`] which
/// provides more flexible executor discovery
/// - The callback pattern ensures thread-safe access to the global executor
/// Sets the global executor for the entire program.
///
/// This function initializes the global executor that will be available throughout
/// the program's lifetime. Once set, the executor can be accessed from anywhere
/// using [`global_executor`].
///
/// # Arguments
///
/// * `runtime` - A boxed [`DynExecutor`] that will serve as the global executor
///
/// # Panics
///
/// This function will panic if called more than once. The global executor can only
/// be initialized once during the program's lifetime.
///
/// # Example
///
/// ```
/// use some_executor::global_executor::set_global_executor;
/// use some_executor::DynExecutor;
///
/// // Early in your program initialization
/// fn init_executor() {
/// let executor: Box<DynExecutor> = todo!(); // Your executor implementation
/// set_global_executor(executor);
/// }
/// ```
///
/// # Best Practices
///
/// - Call this function early in your program's initialization, ideally in `main()`
/// or during startup
/// - Ensure the executor is fully configured before setting it as the global executor
/// - Consider whether you actually need a global executor - in many cases,
/// [`crate::current_executor`] provides a more flexible solution
///
/// # Thread Safety
///
/// This function is thread-safe and uses internal synchronization. However, it should
/// typically be called from a single initialization point to avoid race conditions
/// where multiple threads attempt to set the global executor.