mlx_c_rust/runtime/
stream_defaults.rs1use crate::MlxCError;
5use crate::error::check_status;
6use crate::raw;
7use crate::types::device::MlxDeviceHandle;
8use crate::types::vectors::MlxVectorStream;
9
10#[derive(Debug)]
12pub struct MlxStream(raw::mlx_stream);
13
14impl MlxStream {
15 pub fn default_cpu() -> Result<Self, MlxCError> {
16 let raw_stream = unsafe { raw::mlx_default_cpu_stream_new() };
19 Self::from_raw(raw_stream, "acquire the default MLX CPU stream")
20 }
21
22 pub fn default_gpu() -> Result<Self, MlxCError> {
23 let raw_stream = unsafe { raw::mlx_default_gpu_stream_new() };
26 Self::from_raw(raw_stream, "acquire the default MLX GPU stream")
27 }
28
29 pub fn to_string_lossy(&self) -> Result<String, MlxCError> {
31 let operation: &'static str = "describe an MLX stream";
32 let mut output = crate::MlxString::empty();
33 let status = unsafe { raw::mlx_stream_tostring(output.raw_mut(), self.0) };
36 check_status(status, operation)?;
37 output.require_populated(operation)?;
38 Ok(output.to_string_lossy())
39 }
40
41 pub const fn raw(&self) -> raw::mlx_stream {
42 self.0
43 }
44
45 fn from_raw(raw_stream: raw::mlx_stream, operation: &'static str) -> Result<Self, MlxCError> {
46 if raw_stream.ctx.is_null() {
47 return Err(MlxCError {
48 operation,
49 description: "MLX returned an empty stream handle".to_owned(),
50 });
51 }
52 Ok(Self(raw_stream))
53 }
54
55 pub(crate) fn from_live_raw(
56 raw_stream: raw::mlx_stream,
57 operation: &'static str,
58 ) -> Result<Self, MlxCError> {
59 Self::from_raw(raw_stream, operation)
60 }
61}
62
63impl Drop for MlxStream {
64 fn drop(&mut self) {
65 unsafe {
67 raw::mlx_stream_free(self.0);
68 }
69 }
70}
71
72#[derive(Debug)]
74pub struct MlxStreamThreadLocal(raw::mlx_stream_thread_local);
75
76impl MlxStreamThreadLocal {
77 pub fn for_device(device: &MlxDeviceHandle) -> Result<Self, MlxCError> {
79 let operation: &'static str = "create an MLX thread-local stream slot";
80 let raw_slot = unsafe { raw::mlx_stream_thread_local_new(device.raw()) };
83 if raw_slot.ctx.is_null() {
84 return Err(MlxCError {
85 operation,
86 description: "MLX returned an empty thread-local stream handle".to_owned(),
87 });
88 }
89 Ok(Self(raw_slot))
90 }
91
92 pub fn set(&mut self, source: &Self) -> Result<(), MlxCError> {
94 let status = unsafe { raw::mlx_stream_thread_local_set(&mut self.0, source.0) };
97 check_status(status, "copy an MLX thread-local stream slot")
98 }
99
100 pub fn stream(&self) -> Result<MlxStream, MlxCError> {
102 let operation: &'static str = "read the MLX thread-local stream";
103 let mut raw_stream = raw::mlx_stream {
104 ctx: std::ptr::null_mut(),
105 };
106 let status = unsafe { raw::mlx_stream_from_thread_local(&mut raw_stream, self.0) };
109 check_status(status, operation)?;
110 MlxStream::from_live_raw(raw_stream, operation)
111 }
112
113 pub fn synchronize(&self) -> Result<(), MlxCError> {
115 let status = unsafe { raw::mlx_synchronize_thread_local(self.0) };
117 check_status(status, "synchronize the MLX thread-local stream")
118 }
119}
120
121impl Drop for MlxStreamThreadLocal {
122 fn drop(&mut self) {
123 unsafe {
126 raw::mlx_stream_thread_local_free(self.0);
127 }
128 }
129}
130
131impl MlxStream {
132 pub fn on_device(device: &MlxDeviceHandle) -> Result<Self, MlxCError> {
134 let raw_stream = unsafe { raw::mlx_stream_new_device(device.raw()) };
137 Self::from_raw(raw_stream, "create an MLX stream on a device")
138 }
139
140 pub fn set(&mut self, source: &Self) -> Result<(), MlxCError> {
142 let status = unsafe { raw::mlx_stream_set(&mut self.0, source.0) };
145 check_status(status, "copy an MLX stream")
146 }
147
148 #[must_use]
150 pub fn equals(&self, other: &Self) -> bool {
151 unsafe { raw::mlx_stream_equal(self.0, other.0) }
153 }
154
155 pub fn device(&self) -> Result<MlxDeviceHandle, MlxCError> {
157 let operation: &'static str = "read the MLX stream device";
158 let mut raw_device = raw::mlx_device {
159 ctx: std::ptr::null_mut(),
160 };
161 let status = unsafe { raw::mlx_stream_get_device(&mut raw_device, self.0) };
164 check_status(status, operation)?;
165 MlxDeviceHandle::from_live_raw(raw_device, operation)
166 }
167
168 pub fn index(&self) -> Result<i32, MlxCError> {
170 let operation: &'static str = "read the MLX stream index";
171 let mut stream_index: i32 = 0;
172 let status = unsafe { raw::mlx_stream_get_index(&mut stream_index, self.0) };
175 check_status(status, operation)?;
176 Ok(stream_index)
177 }
178
179 pub fn synchronize(&self) -> Result<(), MlxCError> {
181 let status = unsafe { raw::mlx_synchronize(self.0) };
183 check_status(status, "synchronize an MLX stream")
184 }
185
186 pub fn default_for_device(device: &MlxDeviceHandle) -> Result<Self, MlxCError> {
188 let operation: &'static str = "acquire the MLX device default stream";
189 let mut raw_stream = raw::mlx_stream {
190 ctx: std::ptr::null_mut(),
191 };
192 let status = unsafe { raw::mlx_get_default_stream(&mut raw_stream, device.raw()) };
195 check_status(status, operation)?;
196 Self::from_raw(raw_stream, operation)
197 }
198
199 pub fn all_streams() -> Result<MlxVectorStream, MlxCError> {
201 let operation: &'static str = "list the MLX streams";
202 let mut output = MlxVectorStream::empty();
203 let status = unsafe { raw::mlx_get_streams(output.raw_mut()) };
206 check_status(status, operation)?;
207 Ok(output)
208 }
209}
210
211pub fn clear_streams() -> Result<(), MlxCError> {
213 let status = unsafe { raw::mlx_clear_streams() };
216 check_status(status, "clear the MLX streams")
217}
218
219pub fn set_default_stream(stream: &MlxStream) -> Result<(), MlxCError> {
221 let status = unsafe { raw::mlx_set_default_stream(stream.raw()) };
223 check_status(status, "set the MLX default stream")
224}
225
226pub fn synchronize_all_defaults() -> Result<(), MlxCError> {
228 let status = unsafe { raw::mlx_synchronize_default() };
231 check_status(status, "synchronize the MLX default streams")
232}