interrupt_ref_cell/lib.rs
1//! A [`RefCell`] for sharing data with interrupt handlers or signal handlers on the same thread.
2//!
3//! [`InterruptRefCell`] is just like [`RefCell`], but disables interrupts during borrows.
4//!
5//! See [`std::cell`] for a module-level description of cells.
6//!
7//! # Synchronization
8//!
9//! This cell synchronizes the current thread _with itself_ via a [`compiler_fence`].
10//!
11//! A compiler fence is sufficient for sharing a `!Sync` type, such as [`RefCell`], with an interrupt handler on the same thread.
12//!
13//! [`compiler_fence`]: std::sync::atomic::compiler_fence
14//!
15//! # Caveats
16//!
17//! <div class="warning">Interrupts are disabled on a best-effort basis.</div>
18//!
19//! Holding a reference does not guarantee that interrupts are disabled.
20//! Dropping shared references in the wrong order might enable interrupts prematurely.
21//! Similarly, you can just enable interrupts manually while holding a reference.
22//!
23//! # Examples
24//!
25//! ```
26//! use interrupt_ref_cell::{InterruptRefCell, LocalKeyExt};
27//!
28//! thread_local! {
29//! static X: InterruptRefCell<Vec<i32>> = InterruptRefCell::new(Vec::new());
30//! }
31//!
32//! fn interrupt_handler() {
33//! X.with_borrow_mut(|v| v.push(1));
34//! }
35//! #
36//! # // Setup signal handling for demo
37//! #
38//! # use nix::libc;
39//! # use nix::sys::signal::{self, SigHandler, Signal};
40//! #
41//! # extern "C" fn handle_sigint(_signal: libc::c_int) {
42//! # interrupt_handler();
43//! # }
44//! #
45//! # let handler = SigHandler::Handler(handle_sigint);
46//! # unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
47//! #
48//! # fn raise_interrupt() {
49//! # signal::raise(Signal::SIGINT);
50//! # }
51//!
52//! X.with_borrow(|v| {
53//! // Raise an interrupt
54//! raise_interrupt();
55//! assert_eq!(*v, vec![]);
56//! });
57//!
58//! // The interrupt handler runs
59//!
60//! X.with_borrow(|v| assert_eq!(*v, vec![1]));
61//! ```
62
63#![cfg_attr(target_os = "none", no_std)]
64
65mod interrupt_dropper;
66#[cfg(not(target_os = "none"))]
67mod local_key;
68
69use core::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
70use core::cmp::Ordering;
71use core::ops::{Deref, DerefMut};
72use core::{fmt, mem};
73
74use self::interrupt_dropper::InterruptDropper;
75#[cfg(not(target_os = "none"))]
76pub use self::local_key::LocalKeyExt;
77
78/// A mutable memory location with dynamically checked borrow rules
79///
80/// See the [module-level documentation](self) for more.
81pub struct InterruptRefCell<T: ?Sized> {
82 inner: RefCell<T>,
83}
84
85impl<T: ?Sized + fmt::Debug> fmt::Debug for InterruptRefCell<T> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 let mut d = f.debug_struct("InterruptRefCell");
88 match self.try_borrow() {
89 Ok(borrow) => d.field("value", &borrow),
90 Err(_) => d.field("value", &format_args!("<borrowed>")),
91 };
92 d.finish()
93 }
94}
95
96impl<T> InterruptRefCell<T> {
97 /// Creates a new `InterruptRefCell` containing `value`.
98 ///
99 /// # Examples
100 ///
101 /// ```
102 /// use interrupt_ref_cell::InterruptRefCell;
103 ///
104 /// let c = InterruptRefCell::new(5);
105 /// ```
106 #[inline]
107 pub const fn new(value: T) -> Self {
108 Self {
109 inner: RefCell::new(value),
110 }
111 }
112
113 /// Consumes the `InterruptRefCell`, returning the wrapped value.
114 ///
115 /// # Examples
116 ///
117 /// ```
118 /// use interrupt_ref_cell::InterruptRefCell;
119 ///
120 /// let c = InterruptRefCell::new(5);
121 ///
122 /// let five = c.into_inner();
123 /// ```
124 #[inline]
125 pub fn into_inner(self) -> T {
126 self.inner.into_inner()
127 }
128
129 /// Replaces the wrapped value with a new one, returning the old value,
130 /// without deinitializing either one.
131 ///
132 /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html).
133 ///
134 /// # Panics
135 ///
136 /// Panics if the value is currently borrowed.
137 ///
138 /// # Examples
139 ///
140 /// ```
141 /// use interrupt_ref_cell::InterruptRefCell;
142 /// let cell = InterruptRefCell::new(5);
143 /// let old_value = cell.replace(6);
144 /// assert_eq!(old_value, 5);
145 /// assert_eq!(cell, InterruptRefCell::new(6));
146 /// ```
147 #[inline]
148 #[track_caller]
149 pub fn replace(&self, t: T) -> T {
150 mem::replace(&mut *self.borrow_mut(), t)
151 }
152
153 /// Replaces the wrapped value with a new one computed from `f`, returning
154 /// the old value, without deinitializing either one.
155 ///
156 /// # Panics
157 ///
158 /// Panics if the value is currently borrowed.
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// use interrupt_ref_cell::InterruptRefCell;
164 /// let cell = InterruptRefCell::new(5);
165 /// let old_value = cell.replace_with(|&mut old| old + 1);
166 /// assert_eq!(old_value, 5);
167 /// assert_eq!(cell, InterruptRefCell::new(6));
168 /// ```
169 #[inline]
170 #[track_caller]
171 pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
172 let mut_borrow = &mut *self.borrow_mut();
173 let replacement = f(mut_borrow);
174 mem::replace(mut_borrow, replacement)
175 }
176
177 /// Swaps the wrapped value of `self` with the wrapped value of `other`,
178 /// without deinitializing either one.
179 ///
180 /// This function corresponds to [`std::mem::swap`](../mem/fn.swap.html).
181 ///
182 /// # Panics
183 ///
184 /// Panics if the value in either `InterruptRefCell` is currently borrowed, or
185 /// if `self` and `other` point to the same `InterruptRefCell`.
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// use interrupt_ref_cell::InterruptRefCell;
191 /// let c = InterruptRefCell::new(5);
192 /// let d = InterruptRefCell::new(6);
193 /// c.swap(&d);
194 /// assert_eq!(c, InterruptRefCell::new(6));
195 /// assert_eq!(d, InterruptRefCell::new(5));
196 /// ```
197 #[inline]
198 pub fn swap(&self, other: &Self) {
199 mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
200 }
201}
202
203impl<T: ?Sized> InterruptRefCell<T> {
204 /// Immutably borrows the wrapped value.
205 ///
206 /// The borrow lasts until the returned `InterruptRef` exits scope. Multiple
207 /// immutable borrows can be taken out at the same time.
208 ///
209 /// # Panics
210 ///
211 /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
212 /// [`try_borrow`](#method.try_borrow).
213 ///
214 /// # Examples
215 ///
216 /// ```
217 /// use interrupt_ref_cell::InterruptRefCell;
218 ///
219 /// let c = InterruptRefCell::new(5);
220 ///
221 /// let borrowed_five = c.borrow();
222 /// let borrowed_five2 = c.borrow();
223 /// ```
224 ///
225 /// An example of panic:
226 ///
227 /// ```should_panic
228 /// use interrupt_ref_cell::InterruptRefCell;
229 ///
230 /// let c = InterruptRefCell::new(5);
231 ///
232 /// let m = c.borrow_mut();
233 /// let b = c.borrow(); // this causes a panic
234 /// ```
235 #[inline]
236 #[track_caller]
237 pub fn borrow(&self) -> InterruptRef<'_, T> {
238 self.try_borrow().expect("already mutably borrowed")
239 }
240
241 /// Immutably borrows the wrapped value, returning an error if the value is currently mutably
242 /// borrowed.
243 ///
244 /// The borrow lasts until the returned `InterruptRef` exits scope. Multiple immutable borrows can be
245 /// taken out at the same time.
246 ///
247 /// This is the non-panicking variant of [`borrow`](#method.borrow).
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// use interrupt_ref_cell::InterruptRefCell;
253 ///
254 /// let c = InterruptRefCell::new(5);
255 ///
256 /// {
257 /// let m = c.borrow_mut();
258 /// assert!(c.try_borrow().is_err());
259 /// }
260 ///
261 /// {
262 /// let m = c.borrow();
263 /// assert!(c.try_borrow().is_ok());
264 /// }
265 /// ```
266 #[inline]
267 #[cfg_attr(feature = "debug_interruptrefcell", track_caller)]
268 pub fn try_borrow(&self) -> Result<InterruptRef<'_, T>, BorrowError> {
269 let guard = interrupts::disable();
270 self.inner.try_borrow().map(|inner| {
271 let inner = InterruptDropper::from(inner);
272 InterruptRef { inner, guard }
273 })
274 }
275
276 /// Mutably borrows the wrapped value.
277 ///
278 /// The borrow lasts until the returned `InterruptRefMut` or all `InterruptRefMut`s derived
279 /// from it exit scope. The value cannot be borrowed while this borrow is
280 /// active.
281 ///
282 /// # Panics
283 ///
284 /// Panics if the value is currently borrowed. For a non-panicking variant, use
285 /// [`try_borrow_mut`](#method.try_borrow_mut).
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// use interrupt_ref_cell::InterruptRefCell;
291 ///
292 /// let c = InterruptRefCell::new("hello".to_owned());
293 ///
294 /// *c.borrow_mut() = "bonjour".to_owned();
295 ///
296 /// assert_eq!(&*c.borrow(), "bonjour");
297 /// ```
298 ///
299 /// An example of panic:
300 ///
301 /// ```should_panic
302 /// use interrupt_ref_cell::InterruptRefCell;
303 ///
304 /// let c = InterruptRefCell::new(5);
305 /// let m = c.borrow();
306 ///
307 /// let b = c.borrow_mut(); // this causes a panic
308 /// ```
309 #[inline]
310 #[track_caller]
311 pub fn borrow_mut(&self) -> InterruptRefMut<'_, T> {
312 self.try_borrow_mut().expect("already borrowed")
313 }
314
315 /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
316 ///
317 /// The borrow lasts until the returned `InterruptRefMut` or all `InterruptRefMut`s derived
318 /// from it exit scope. The value cannot be borrowed while this borrow is
319 /// active.
320 ///
321 /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
322 ///
323 /// # Examples
324 ///
325 /// ```
326 /// use interrupt_ref_cell::InterruptRefCell;
327 ///
328 /// let c = InterruptRefCell::new(5);
329 ///
330 /// {
331 /// let m = c.borrow();
332 /// assert!(c.try_borrow_mut().is_err());
333 /// }
334 ///
335 /// assert!(c.try_borrow_mut().is_ok());
336 /// ```
337 #[inline]
338 #[cfg_attr(feature = "debug_interruptrefcell", track_caller)]
339 pub fn try_borrow_mut(&self) -> Result<InterruptRefMut<'_, T>, BorrowMutError> {
340 let guard = interrupts::disable();
341 self.inner.try_borrow_mut().map(|inner| {
342 let inner = InterruptDropper::from(inner);
343 InterruptRefMut { inner, guard }
344 })
345 }
346
347 /// Returns a raw pointer to the underlying data in this cell.
348 ///
349 /// # Examples
350 ///
351 /// ```
352 /// use interrupt_ref_cell::InterruptRefCell;
353 ///
354 /// let c = InterruptRefCell::new(5);
355 ///
356 /// let ptr = c.as_ptr();
357 /// ```
358 #[inline]
359 pub fn as_ptr(&self) -> *mut T {
360 self.inner.as_ptr()
361 }
362
363 /// Returns a mutable reference to the underlying data.
364 ///
365 /// Since this method borrows `InterruptRefCell` mutably, it is statically guaranteed
366 /// that no borrows to the underlying data exist. The dynamic checks inherent
367 /// in [`borrow_mut`] and most other methods of `InterruptRefCell` are therefore
368 /// unnecessary.
369 ///
370 /// This method can only be called if `InterruptRefCell` can be mutably borrowed,
371 /// which in general is only the case directly after the `InterruptRefCell` has
372 /// been created. In these situations, skipping the aforementioned dynamic
373 /// borrowing checks may yield better ergonomics and runtime-performance.
374 ///
375 /// In most situations where `InterruptRefCell` is used, it can't be borrowed mutably.
376 /// Use [`borrow_mut`] to get mutable access to the underlying data then.
377 ///
378 /// [`borrow_mut`]: InterruptRefCell::borrow_mut()
379 ///
380 /// # Examples
381 ///
382 /// ```
383 /// use interrupt_ref_cell::InterruptRefCell;
384 ///
385 /// let mut c = InterruptRefCell::new(5);
386 /// *c.get_mut() += 1;
387 ///
388 /// assert_eq!(c, InterruptRefCell::new(6));
389 /// ```
390 #[inline]
391 pub fn get_mut(&mut self) -> &mut T {
392 self.inner.get_mut()
393 }
394
395 /// Immutably borrows the wrapped value, returning an error if the value is
396 /// currently mutably borrowed.
397 ///
398 /// # Safety
399 ///
400 /// Unlike `InterruptRefCell::borrow`, this method is unsafe because it does not
401 /// return a `InterruptRef`, thus leaving the borrow flag untouched. Mutably
402 /// borrowing the `InterruptRefCell` while the reference returned by this method
403 /// is alive is undefined behaviour.
404 ///
405 /// # Examples
406 ///
407 /// ```
408 /// use interrupt_ref_cell::InterruptRefCell;
409 ///
410 /// let c = InterruptRefCell::new(5);
411 ///
412 /// {
413 /// let m = c.borrow_mut();
414 /// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
415 /// }
416 ///
417 /// {
418 /// let m = c.borrow();
419 /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
420 /// }
421 /// ```
422 #[inline]
423 pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
424 let guard = interrupts::disable();
425 let ret = self.inner.try_borrow_unguarded();
426 drop(guard);
427 ret
428 }
429}
430
431impl<T: Default> InterruptRefCell<T> {
432 /// Takes the wrapped value, leaving `Default::default()` in its place.
433 ///
434 /// # Panics
435 ///
436 /// Panics if the value is currently borrowed.
437 ///
438 /// # Examples
439 ///
440 /// ```
441 /// use interrupt_ref_cell::InterruptRefCell;
442 ///
443 /// let c = InterruptRefCell::new(5);
444 /// let five = c.take();
445 ///
446 /// assert_eq!(five, 5);
447 /// assert_eq!(c.into_inner(), 0);
448 /// ```
449 pub fn take(&self) -> T {
450 self.replace(Default::default())
451 }
452}
453
454impl<T: Clone> Clone for InterruptRefCell<T> {
455 /// # Panics
456 ///
457 /// Panics if the value is currently mutably borrowed.
458 #[inline]
459 #[track_caller]
460 fn clone(&self) -> InterruptRefCell<T> {
461 InterruptRefCell::new(self.borrow().clone())
462 }
463
464 /// # Panics
465 ///
466 /// Panics if `other` is currently mutably borrowed.
467 #[inline]
468 #[track_caller]
469 fn clone_from(&mut self, other: &Self) {
470 self.get_mut().clone_from(&other.borrow())
471 }
472}
473
474impl<T: Default> Default for InterruptRefCell<T> {
475 /// Creates a `InterruptRefCell<T>`, with the `Default` value for T.
476 #[inline]
477 fn default() -> InterruptRefCell<T> {
478 InterruptRefCell::new(Default::default())
479 }
480}
481
482impl<T: ?Sized + PartialEq> PartialEq for InterruptRefCell<T> {
483 /// # Panics
484 ///
485 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
486 #[inline]
487 fn eq(&self, other: &InterruptRefCell<T>) -> bool {
488 *self.borrow() == *other.borrow()
489 }
490}
491
492impl<T: ?Sized + Eq> Eq for InterruptRefCell<T> {}
493
494impl<T: ?Sized + PartialOrd> PartialOrd for InterruptRefCell<T> {
495 /// # Panics
496 ///
497 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
498 #[inline]
499 fn partial_cmp(&self, other: &InterruptRefCell<T>) -> Option<Ordering> {
500 self.borrow().partial_cmp(&*other.borrow())
501 }
502
503 /// # Panics
504 ///
505 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
506 #[inline]
507 fn lt(&self, other: &InterruptRefCell<T>) -> bool {
508 *self.borrow() < *other.borrow()
509 }
510
511 /// # Panics
512 ///
513 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
514 #[inline]
515 fn le(&self, other: &InterruptRefCell<T>) -> bool {
516 *self.borrow() <= *other.borrow()
517 }
518
519 /// # Panics
520 ///
521 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
522 #[inline]
523 fn gt(&self, other: &InterruptRefCell<T>) -> bool {
524 *self.borrow() > *other.borrow()
525 }
526
527 /// # Panics
528 ///
529 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
530 #[inline]
531 fn ge(&self, other: &InterruptRefCell<T>) -> bool {
532 *self.borrow() >= *other.borrow()
533 }
534}
535
536impl<T: ?Sized + Ord> Ord for InterruptRefCell<T> {
537 /// # Panics
538 ///
539 /// Panics if the value in either `InterruptRefCell` is currently mutably borrowed.
540 #[inline]
541 fn cmp(&self, other: &InterruptRefCell<T>) -> Ordering {
542 self.borrow().cmp(&*other.borrow())
543 }
544}
545
546impl<T> From<T> for InterruptRefCell<T> {
547 /// Creates a new `InterruptRefCell<T>` containing the given value.
548 fn from(t: T) -> InterruptRefCell<T> {
549 InterruptRefCell::new(t)
550 }
551}
552
553/// Wraps a borrowed reference to a value in a `InterruptRefCell` box.
554/// A wrapper type for an immutably borrowed value from a `InterruptRefCell<T>`.
555///
556/// See the [module-level documentation](self) for more.
557pub struct InterruptRef<'b, T: ?Sized + 'b> {
558 inner: InterruptDropper<Ref<'b, T>>,
559 guard: interrupts::Guard,
560}
561
562impl<T: ?Sized> Deref for InterruptRef<'_, T> {
563 type Target = T;
564
565 #[inline]
566 fn deref(&self) -> &Self::Target {
567 self.inner.deref()
568 }
569}
570
571impl<'b, T: ?Sized> InterruptRef<'b, T> {
572 /// Copies a `InterruptRef`.
573 ///
574 /// The `InterruptRefCell` is already immutably borrowed, so this cannot fail.
575 ///
576 /// This is an associated function that needs to be used as
577 /// `InterruptRef::clone(...)`. A `Clone` implementation or a method would interfere
578 /// with the widespread use of `r.borrow().clone()` to clone the contents of
579 /// a `InterruptRefCell`.
580 #[allow(clippy::should_implement_trait)]
581 #[must_use]
582 #[inline]
583 pub fn clone(orig: &InterruptRef<'b, T>) -> InterruptRef<'b, T> {
584 let guard = interrupts::disable();
585 let inner = InterruptDropper::from(Ref::clone(&orig.inner));
586 InterruptRef { inner, guard }
587 }
588
589 /// Makes a new `InterruptRef` for a component of the borrowed data.
590 ///
591 /// The `InterruptRefCell` is already immutably borrowed, so this cannot fail.
592 ///
593 /// This is an associated function that needs to be used as `InterruptRef::map(...)`.
594 /// A method would interfere with methods of the same name on the contents
595 /// of a `InterruptRefCell` used through `Deref`.
596 ///
597 /// # Examples
598 ///
599 /// ```
600 /// use interrupt_ref_cell::{InterruptRefCell, InterruptRef};
601 ///
602 /// let c = InterruptRefCell::new((5, 'b'));
603 /// let b1: InterruptRef<'_, (u32, char)> = c.borrow();
604 /// let b2: InterruptRef<'_, u32> = InterruptRef::map(b1, |t| &t.0);
605 /// assert_eq!(*b2, 5)
606 /// ```
607 #[inline]
608 pub fn map<U: ?Sized, F>(orig: InterruptRef<'b, T>, f: F) -> InterruptRef<'b, U>
609 where
610 F: FnOnce(&T) -> &U,
611 {
612 let InterruptRef { inner, guard } = orig;
613 let inner = InterruptDropper::from(Ref::map(InterruptDropper::into_inner(inner), f));
614 InterruptRef { inner, guard }
615 }
616
617 /// Makes a new `InterruptRef` for an optional component of the borrowed data. The
618 /// original guard is returned as an `Err(..)` if the closure returns
619 /// `None`.
620 ///
621 /// The `InterruptRefCell` is already immutably borrowed, so this cannot fail.
622 ///
623 /// This is an associated function that needs to be used as
624 /// `InterruptRef::filter_map(...)`. A method would interfere with methods of the same
625 /// name on the contents of a `InterruptRefCell` used through `Deref`.
626 ///
627 /// # Examples
628 ///
629 /// ```
630 /// use interrupt_ref_cell::{InterruptRefCell, InterruptRef};
631 ///
632 /// let c = InterruptRefCell::new(vec![1, 2, 3]);
633 /// let b1: InterruptRef<'_, Vec<u32>> = c.borrow();
634 /// let b2: Result<InterruptRef<'_, u32>, _> = InterruptRef::filter_map(b1, |v| v.get(1));
635 /// assert_eq!(*b2.unwrap(), 2);
636 /// ```
637 #[allow(clippy::result_large_err)]
638 #[inline]
639 pub fn filter_map<U: ?Sized, F>(
640 orig: InterruptRef<'b, T>,
641 f: F,
642 ) -> Result<InterruptRef<'b, U>, Self>
643 where
644 F: FnOnce(&T) -> Option<&U>,
645 {
646 let guard = interrupts::disable();
647 let filter_map = Ref::filter_map(InterruptDropper::into_inner(orig.inner), f);
648 drop(guard);
649 match filter_map {
650 Ok(inner) => {
651 let inner = InterruptDropper::from(inner);
652 Ok(InterruptRef {
653 inner,
654 guard: orig.guard,
655 })
656 }
657 Err(inner) => {
658 let inner = InterruptDropper::from(inner);
659 Err(InterruptRef {
660 inner,
661 guard: orig.guard,
662 })
663 }
664 }
665 }
666
667 /// Splits a `InterruptRef` into multiple `InterruptRef`s for different components of the
668 /// borrowed data.
669 ///
670 /// The `InterruptRefCell` is already immutably borrowed, so this cannot fail.
671 ///
672 /// This is an associated function that needs to be used as
673 /// `InterruptRef::map_split(...)`. A method would interfere with methods of the same
674 /// name on the contents of a `InterruptRefCell` used through `Deref`.
675 ///
676 /// # Examples
677 ///
678 /// ```
679 /// use interrupt_ref_cell::{InterruptRefCell, InterruptRef};
680 ///
681 /// let cell = InterruptRefCell::new([1, 2, 3, 4]);
682 /// let borrow = cell.borrow();
683 /// let (begin, end) = InterruptRef::map_split(borrow, |slice| slice.split_at(2));
684 /// assert_eq!(*begin, [1, 2]);
685 /// assert_eq!(*end, [3, 4]);
686 /// ```
687 #[inline]
688 pub fn map_split<U: ?Sized, V: ?Sized, F>(
689 orig: InterruptRef<'b, T>,
690 f: F,
691 ) -> (InterruptRef<'b, U>, InterruptRef<'b, V>)
692 where
693 F: FnOnce(&T) -> (&U, &V),
694 {
695 let guard = interrupts::disable();
696 let (a, b) = Ref::map_split(InterruptDropper::into_inner(orig.inner), f);
697 (
698 InterruptRef {
699 inner: InterruptDropper::from(a),
700 guard,
701 },
702 InterruptRef {
703 inner: InterruptDropper::from(b),
704 guard: orig.guard,
705 },
706 )
707 }
708}
709
710impl<T: ?Sized + fmt::Debug> fmt::Debug for InterruptRef<'_, T> {
711 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
712 self.inner.fmt(f)
713 }
714}
715
716impl<T: ?Sized + fmt::Display> fmt::Display for InterruptRef<'_, T> {
717 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
718 self.inner.fmt(f)
719 }
720}
721
722impl<'b, T: ?Sized> InterruptRefMut<'b, T> {
723 /// Makes a new `InterruptRefMut` for a component of the borrowed data, e.g., an enum
724 /// variant.
725 ///
726 /// The `InterruptRefCell` is already mutably borrowed, so this cannot fail.
727 ///
728 /// This is an associated function that needs to be used as
729 /// `InterruptRefMut::map(...)`. A method would interfere with methods of the same
730 /// name on the contents of a `InterruptRefCell` used through `Deref`.
731 ///
732 /// # Examples
733 ///
734 /// ```
735 /// use interrupt_ref_cell::{InterruptRefCell, InterruptRefMut};
736 ///
737 /// let c = InterruptRefCell::new((5, 'b'));
738 /// {
739 /// let b1: InterruptRefMut<'_, (u32, char)> = c.borrow_mut();
740 /// let mut b2: InterruptRefMut<'_, u32> = InterruptRefMut::map(b1, |t| &mut t.0);
741 /// assert_eq!(*b2, 5);
742 /// *b2 = 42;
743 /// }
744 /// assert_eq!(*c.borrow(), (42, 'b'));
745 /// ```
746 #[inline]
747 pub fn map<U: ?Sized, F>(orig: InterruptRefMut<'b, T>, f: F) -> InterruptRefMut<'b, U>
748 where
749 F: FnOnce(&mut T) -> &mut U,
750 {
751 let InterruptRefMut { inner, guard } = orig;
752 let inner = InterruptDropper::from(RefMut::map(InterruptDropper::into_inner(inner), f));
753 InterruptRefMut { inner, guard }
754 }
755
756 /// Makes a new `InterruptRefMut` for an optional component of the borrowed data. The
757 /// original guard is returned as an `Err(..)` if the closure returns
758 /// `None`.
759 ///
760 /// The `InterruptRefCell` is already mutably borrowed, so this cannot fail.
761 ///
762 /// This is an associated function that needs to be used as
763 /// `InterruptRefMut::filter_map(...)`. A method would interfere with methods of the
764 /// same name on the contents of a `InterruptRefCell` used through `Deref`.
765 ///
766 /// # Examples
767 ///
768 /// ```
769 /// use interrupt_ref_cell::{InterruptRefCell, InterruptRefMut};
770 ///
771 /// let c = InterruptRefCell::new(vec![1, 2, 3]);
772 ///
773 /// {
774 /// let b1: InterruptRefMut<'_, Vec<u32>> = c.borrow_mut();
775 /// let mut b2: Result<InterruptRefMut<'_, u32>, _> = InterruptRefMut::filter_map(b1, |v| v.get_mut(1));
776 ///
777 /// if let Ok(mut b2) = b2 {
778 /// *b2 += 2;
779 /// }
780 /// }
781 ///
782 /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
783 /// ```
784 #[allow(clippy::result_large_err)]
785 #[inline]
786 pub fn filter_map<U: ?Sized, F>(
787 orig: InterruptRefMut<'b, T>,
788 f: F,
789 ) -> Result<InterruptRefMut<'b, U>, Self>
790 where
791 F: FnOnce(&mut T) -> Option<&mut U>,
792 {
793 let guard = interrupts::disable();
794 let filter_map = RefMut::filter_map(InterruptDropper::into_inner(orig.inner), f);
795 drop(guard);
796 match filter_map {
797 Ok(inner) => {
798 let inner = InterruptDropper::from(inner);
799 Ok(InterruptRefMut {
800 inner,
801 guard: orig.guard,
802 })
803 }
804 Err(inner) => {
805 let inner = InterruptDropper::from(inner);
806 Err(InterruptRefMut {
807 inner,
808 guard: orig.guard,
809 })
810 }
811 }
812 }
813
814 /// Splits a `InterruptRefMut` into multiple `InterruptRefMut`s for different components of the
815 /// borrowed data.
816 ///
817 /// The underlying `InterruptRefCell` will remain mutably borrowed until both
818 /// returned `InterruptRefMut`s go out of scope.
819 ///
820 /// The `InterruptRefCell` is already mutably borrowed, so this cannot fail.
821 ///
822 /// This is an associated function that needs to be used as
823 /// `InterruptRefMut::map_split(...)`. A method would interfere with methods of the
824 /// same name on the contents of a `InterruptRefCell` used through `Deref`.
825 ///
826 /// # Examples
827 ///
828 /// ```
829 /// use interrupt_ref_cell::{InterruptRefCell, InterruptRefMut};
830 ///
831 /// let cell = InterruptRefCell::new([1, 2, 3, 4]);
832 /// let borrow = cell.borrow_mut();
833 /// let (mut begin, mut end) = InterruptRefMut::map_split(borrow, |slice| slice.split_at_mut(2));
834 /// assert_eq!(*begin, [1, 2]);
835 /// assert_eq!(*end, [3, 4]);
836 /// begin.copy_from_slice(&[4, 3]);
837 /// end.copy_from_slice(&[2, 1]);
838 /// ```
839 #[inline]
840 pub fn map_split<U: ?Sized, V: ?Sized, F>(
841 orig: InterruptRefMut<'b, T>,
842 f: F,
843 ) -> (InterruptRefMut<'b, U>, InterruptRefMut<'b, V>)
844 where
845 F: FnOnce(&mut T) -> (&mut U, &mut V),
846 {
847 let guard = interrupts::disable();
848 let (a, b) = RefMut::map_split(InterruptDropper::into_inner(orig.inner), f);
849 (
850 InterruptRefMut {
851 inner: InterruptDropper::from(a),
852 guard,
853 },
854 InterruptRefMut {
855 inner: InterruptDropper::from(b),
856 guard: orig.guard,
857 },
858 )
859 }
860}
861
862/// A wrapper type for a mutably borrowed value from a `InterruptRefCell<T>`.
863///
864/// See the [module-level documentation](self) for more.
865pub struct InterruptRefMut<'b, T: ?Sized + 'b> {
866 inner: InterruptDropper<RefMut<'b, T>>,
867 guard: interrupts::Guard,
868}
869
870impl<T: ?Sized> Deref for InterruptRefMut<'_, T> {
871 type Target = T;
872
873 #[inline]
874 fn deref(&self) -> &Self::Target {
875 self.inner.deref()
876 }
877}
878
879impl<T: ?Sized> DerefMut for InterruptRefMut<'_, T> {
880 #[inline]
881 fn deref_mut(&mut self) -> &mut Self::Target {
882 self.inner.deref_mut()
883 }
884}
885
886impl<T: ?Sized + fmt::Debug> fmt::Debug for InterruptRefMut<'_, T> {
887 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
888 self.inner.fmt(f)
889 }
890}
891
892impl<T: ?Sized + fmt::Display> fmt::Display for InterruptRefMut<'_, T> {
893 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
894 self.inner.fmt(f)
895 }
896}