Add owned guard types to standard library

tokio provides some owned guard types, like:

async-lock also has something similar:

The common pattern is that they are all created from Arc of some type. I found this pattern very useful.

Does it make sense to add this feature to some of the standard library types? For example:

  • Add to Rc<RefCell<T>>:
    • borrow_owned,
    • try_borrow_owned,
    • borrow_mut_owned,
    • try_borrow_mut_owned.
  • Add to Arc<Mutex<T>>:
    • lock_owned,
    • try_lock_owned.
  • Add to Arc<RwLock<T>>:
    • read_owned,
    • try_read_owned,
    • write_owned,
    • try_write_owned.
1 Like

I think it would be useful to have these in std because it's difficult to guarantee for outside crates they're upholding all the necessary invariants.

1 Like

There is an open feature to add this to parking-lot.

What's the motivation/use-case for adding those; what problem does it solve?


Though, there is a crate that claims to

1 Like

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.
        } else if let Some(node) = stack.pop() {
            let node_ref = node.borrow(); // <- Borrow.


            root = node_ref.right.clone();
        } else {


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.


(I know this can be done using channels, but someone may consider channels being too heavy for simple cases.)


The first example is a good example, the second one won't ever work, because MutexGuard is !Send and an owned version won't change that.

1 Like

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.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.