ax_runtime/thread/lifecycle/
publication.rs1use super::*;
4
5impl PreparedThread {
6 pub fn thread_handle(&self) -> ThreadHandle {
8 self.handle
9 .as_ref()
10 .expect("prepared thread was already consumed")
11 .clone()
12 }
13
14 pub fn publish(self) -> Result<ThreadHandle, TaskError> {
17 Ok(self.stage()?.activate())
18 }
19
20 pub fn stage(mut self) -> Result<StagedThread, TaskError> {
29 let handle = self
30 .handle
31 .take()
32 .expect("prepared thread was already consumed");
33 publish_prepared_thread(self.system, handle).map(|handle| StagedThread {
34 handle: Some(handle),
35 start: Arc::clone(&self.start),
36 })
37 }
38
39 pub(in crate::thread) fn new(
40 system: &'static TaskSystem,
41 handle: ThreadHandle,
42 start: Arc<RuntimeThreadStart>,
43 ) -> Self {
44 Self {
45 system,
46 handle: Some(handle),
47 start,
48 }
49 }
50}
51
52impl StagedThread {
53 pub fn thread_handle(&self) -> ThreadHandle {
55 self.handle
56 .as_ref()
57 .expect("staged thread was already consumed")
58 .clone()
59 }
60
61 pub fn activate(mut self) -> ThreadHandle {
63 let handle = self
64 .handle
65 .take()
66 .expect("staged thread was already consumed");
67 self.start.activate();
68 handle
69 }
70}
71
72impl Drop for StagedThread {
73 fn drop(&mut self) {
74 self.start.abort();
75 }
76}
77
78impl Drop for PreparedThread {
79 fn drop(&mut self) {
80 if let Some(handle) = self.handle.take() {
81 cleanup_failed_thread(self.system, handle);
82 }
83 }
84}
85
86impl RuntimeThreadStart {
87 pub(in crate::thread) const fn new() -> Self {
88 Self {
89 state: AtomicU8::new(THREAD_START_PENDING),
90 wait: WaitQueue::new(),
91 }
92 }
93
94 fn activate(&self) {
95 self.state
96 .compare_exchange(
97 THREAD_START_PENDING,
98 THREAD_START_ACTIVE,
99 Ordering::AcqRel,
100 Ordering::Acquire,
101 )
102 .unwrap_or_else(|state| panic!("invalid staged-thread activation state: {state}"));
103 self.wait.notify_all();
104 }
105
106 fn abort(&self) {
107 if self
108 .state
109 .compare_exchange(
110 THREAD_START_PENDING,
111 THREAD_START_ABORTED,
112 Ordering::AcqRel,
113 Ordering::Acquire,
114 )
115 .is_ok()
116 {
117 self.wait.notify_all();
118 }
119 }
120
121 pub(in crate::thread) fn wait_for_activation(&self) -> bool {
122 match self.state.load(Ordering::Acquire) {
123 THREAD_START_ACTIVE => return true,
124 THREAD_START_ABORTED => return false,
125 THREAD_START_PENDING => {}
126 state => panic!("invalid runtime thread-start state: {state}"),
127 }
128 self.wait
129 .wait_until(|| self.state.load(Ordering::Acquire) != THREAD_START_PENDING);
130 match self.state.load(Ordering::Acquire) {
131 THREAD_START_ACTIVE => true,
132 THREAD_START_ABORTED => false,
133 state => panic!("invalid completed thread-start state: {state}"),
134 }
135 }
136}
137
138fn publish_prepared_thread(
139 system: &'static TaskSystem,
140 handle: ThreadHandle,
141) -> Result<ThreadHandle, TaskError> {
142 let result = with_current_cpu_local_mut_owner(|cpu| system.start_thread(cpu, handle.id()));
143 if let Err(error) = result {
144 cleanup_failed_thread(system, handle);
145 return Err(error);
146 }
147 Ok(handle)
148}
149
150fn cleanup_failed_thread(system: &TaskSystem, handle: ThreadHandle) {
151 let thread = handle.id();
152 let _ = system.mark_exited(thread);
153 drop(handle);
154 let _ = system.reap_thread(thread);
155}