Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

add unique-(a)rc APIs #6

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.

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

Successfully merging this pull request may close these issues.

2 participants