The owned guard has 'static lifetime. You can store them into data structures or return them from a function without the lifetime constraint that normal borrowing guards have.
For example, here is a function that traverses a binary tree iteratively:
use std::cell::RefCell;
use std::rc::Rc;
// Using `Box` here may be better for real codes, but it is outside the scope.
// For now, just assume this is provided by some third party, and I can’t
// change its definition.
pub struct TreeNode {
pub val: i32,
pub left: Option<Rc<RefCell<Self>>>,
pub right: Option<Rc<RefCell<Self>>>,
}
pub fn inorder_traversal(mut root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut result = Vec::new();
let mut stack = Vec::new();
loop {
if let Some(node) = root {
root = node.borrow().left.clone(); // <- Borrow.
stack.push(node);
} else if let Some(node) = stack.pop() {
let node_ref = node.borrow(); // <- Borrow.
result.push(node_ref.val);
root = node_ref.right.clone();
} else {
break;
}
}
result
}
Note that I called borrow before pushing a node into a stack, and borrowed again after popping it out of the stack. If I can have an owned guard, I can just push the guard into the stack, then after popping the guard out of the stack, I don’t have to borrow it again.
Another possible usage is that I can implement thread notification using owned mutex guard:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let mutex = Arc::new(Mutex::new(()));
let guard = Arc::clone(&mutex).lock_owned().unwrap(); // Using imaginary `lock_owned` method.
let sender = thread::spawn(move || {
drop(guard); // Unlock the mutex to notify the receiver thread.
});
let receiver = thread::spawn(move || {
mutex.lock().unwrap(); // Wait for the signal from the sender thread.
});
sender.join().unwrap();
receiver.join().unwrap();
}
(I know this can be done using channels, but someone may consider channels being too heavy for simple cases.)
Fair enough, but it could still be done with parking_lot, since its mutex guard can be Send, although through a feature switch. I think @bjorn3 is referring to Amanieu/parking_lot#273.