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

Possibility of exposing RcBox for transferring allocations between Box and Rc #1283

Open
glaebhoerl opened this issue Sep 16, 2015 · 7 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Comments

@glaebhoerl
Copy link
Contributor

The idea occasionally comes up of whether Rc could take ownership of a Box and re-use the allocation, or conversely of converting a uniquely-owned Rc into a Box. While logically intuitive, this runs up against the physical limitation that Rc stores the reference counts inline in the allocation, ahead of the data, and so the two would not be compatible as-is. Making Rc store the reference counts out of line in a separate allocation (like std::shared_ptr) doesn't seem to be worth the overhead just to support this case.

If, however, we were to consider the ability to avoid some allocations in this way important enough, we do have a fairly straightforward option available to us to support it in some cases: publicly expose the RcBox type which comprises an Rc allocation (without necessarily providing access to the internal RcBox of any Rc - just the type). Something like this:

#[derive(Copy, Clone)]
pub struct RcBox<T: ?Sized> {
    strong: Cell<usize>, // private
    weak:   Cell<usize>, // private
    pub value: T
}

impl<T> RcBox<T> {
    pub fn new(value: T) -> RcBox<T> { ... }
}

impl<T: ?Sized> Rc<T> {
    pub fn from_box(source: Box<RcBox<T>>) -> Rc<T> { ... }
}

pub fn try_into_box<T: ?Sized>(self: Rc<T>) -> Result<Box<RcBox<T>>, Rc<T>> { ... }

(By keeping the reference count fields private, we can ensure that the reference count of any RcBox not currently inside of an Rc is always 1, so that from_box doesn't even need to check or reset them.)

@bluss
Copy link
Member

bluss commented Sep 18, 2015

@eddyb Has some ideas for how custom allocator support can make this easier, without having to expose anything.

@eddyb
Copy link
Member

eddyb commented Sep 18, 2015

That would be #1138.

@glaebhoerl
Copy link
Contributor Author

Even cooler :)

@nrc nrc added T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC. labels Aug 22, 2016
@le-jzr
Copy link

le-jzr commented Apr 21, 2017

Why not make the (current) RcBox #repr(C) and put strong and weak fields after the data? That way, we could simply realloc the box with strong possibility of reusing the original memory. It's not guaranteed, but it would be much better than current state with no drawbacks.

@eddyb
Copy link
Member

eddyb commented Apr 21, 2017

after the data
Doesn't work with DSTs, which both Rc and Arc support.

@eddyb eddyb closed this as completed Apr 21, 2017
@eddyb
Copy link
Member

eddyb commented Apr 21, 2017

Errr, GitHub, I didn't want to do that!

@eddyb eddyb reopened this Apr 21, 2017
@le-jzr
Copy link

le-jzr commented Apr 21, 2017

after the data

Doesn't work with DSTs, which both Rc and Arc support.

Ah, right. Although I'm sure that could be worked around with some raw pointer shenanigans. But that would invalidate the "no drawbacks" part, because of much uglier implementation. :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

5 participants