Skip to content

add unique-(a)rc APIs #6

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Dec 31, 2024
Merged

Conversation

steffahn
Copy link
Contributor

As explained in #1 (comment)

Example use-case:

use mutcursor::{unique::UniqueExt, MutCursorRootedVec};
use std::sync::Arc;

type Link = Option<Arc<BinaryNode>>;
struct Binary(Link);
struct BinaryNode {
    left: Link,
    val: u16,
    right: Link,
}

let binary = Binary(Some(Arc::new(BinaryNode {
    left: Some(Arc::new(BinaryNode {
        left: None,
        val: 42,
        right: None,
    })),
    val: 1337,
    right: None,
})));
let mut node_stack = MutCursorRootedVec::<'static, Binary, BinaryNode>::new(binary);

// Begin traversal from the root
node_stack.advance_from_root(|v| Arc::get_unique(v.0.as_mut()?));

// // Traverse to the leftmost node
while node_stack.advance(|node| Arc::get_mut(node.left.as_mut()?)) {}

assert_eq!(node_stack.top().unwrap().val, 42);

@luketpeterson luketpeterson merged commit 418ff77 into luketpeterson:main Dec 31, 2024
@luketpeterson
Copy link
Owner

luketpeterson commented Dec 31, 2024

This is great. I wonder if the unique A/Rc would be useful as a stand-alone crate?

I suppose aspects like the double-indirection might be inappropriate for a stand-alone version and having it right here makes it easy for people to find.

I added a bit more documentation and published the latest work.

Thanks again for everything. You really enhanced the level of quality in the crate across the board. (and showed me some patterns I will use for all crates going forwards, e.g. with docs links in a README)

@steffahn
Copy link
Contributor Author

Regarding the README links, I searched for a solution of that on the fly and found one mentioned here. In other words, I just learned that myself, too, while doing it :-)

Unique-(a)rc could be useful as standalone, but that's a lot more work. As you can probably guess, the API included here is deliberately minimalist; if going all-in, one could probably mirror half of the API of Box. But really, all we need here is the get_unique/make_unique, and the stable DerefMut. (The Send/Sync is thrown in for good measure.)

The (&mut Self) -> Option<&mut UniqueArc<T>>/(&mut Self) -> &mut UniqueArc<T> API design for those two methods is borrowed from what I found on triomphe’s Arc::{get_unique, make_unique}

The standard library is also working on a – slightly (but also significantly) different – version of unique variants of rc pointers. (Their version allows creation of not-yet-initialized Weak pointers along the side; though that also forces certain restrictions, e.g. no Send/Sync for the rc one, and I recently noticed it would need to come with an invariance restriction as well.)

Finally, IMO, the standard library could also offer Box-like fully-owned variants of Rc/Arc even more nicely, by adapting Box, either in the form of public RcInner<T> wrapper (containing T and space for the counter; presumably with a safety invariant that these counters are private and always fixed at containing the precise value of “1 strong, no additional weak”), and zero-cost conversions from Box<RcInner<T>> to Rc<T> and Arc<T>, or in the form of a AllocateWithCounters-kind of wrapper around the allocator (in the context of the also-in-development allocator API), so you could zero-cost convert from Box<T, AllocateWithCounters<A>> to Rc<T, A> and Arc<T, A>. That is not to say that a separate crate couldn't be helpful, but it's inherently limited by aspects such as the fact that the internal layout of Rc/Arc is unstable, and Box has much compiler-magic for convenience features that other types might likely never be able to replicate.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants