In Pin, we disable as_mut so we can not get a &mut for functions like std::mem::swap that will move the object.
However, somehow we need interior mutability without any moving. In the following code, SimpleNUnPin impls !Unpin so we can't move it. However, we can change its field a, this operator does not change address of the SimpleNUnPin instance.
struct SimpleNUnPin {
a: u64,
}
impl !Unpin for SimpleNUnPin {}
fn main()
{
let x = SimpleNUnPin { a: 1 };
pin_utils::pin_mut!(x);
x.as_mut().a = 2;
}
I want to find a way that enable interior mutability in Pin. I found pin-cell crate, which claims to be safer than RefCell. However, is that what I want? I find no example of it except from some API documentations. I tried to write some codes, but they can't compile.
use std::borrow::BorrowMut;
use pin_cell;
use pin_cell::{PinCell, PinMut};
fn main() {
let x = SimpleNUnPin { a: 1 };
let ptr1 = &x as *const _ as isize;
let xp = PinCell::new(x);
let mut b = xp.borrow_mut();
b.a = 2;
unsafe {
let n1 = &*(ptr1 as *const SimpleNUnPin);
assert_eq!(n1.a, 2);
}
The above code prints out error "error[E0609]: no field a on type &mut PinCell<SimpleNUnPin>". It is quite strange since my clion think it is a PinMut<SimpleNUnpin>.
Is there anyone can help? There are two questions:
Is pin-cell suitable in my case?
Why my code cam't compile, and has a contradict type dedution with clion?
Related
I need to unsafely define a Rust struct that I can share between 2 threads and mutate the content of the struct from both threads.
I do not want to use Mutex nor RwLock because I want to implement the thread safety myself. For performance concerns, I do not want to check the mutex when time I want to access the content and I know it is not in the critical section.
If I only use Arc to share the struct between threads, I get cannot borrow data in an Arc as mutable and help: trait DerefMut is required to modify through a dereference, but it is not implemented for std::sync::Arc<Foo>.
The safe way to do this:
struct Foo {
bar: usize,
}
impl Foo {
pub fn set_bar(&mut self, a: usize) {
self.bar = a;
}
}
fn main() {
let mut foo = Foo { bar: 32 };
foo.bar = 33;
let foo_arc = std::sync::Arc::new(std::sync::Mutex::new(foo));
let foo_arc_2 = std::sync::Arc::clone(&foo_arc);
let handle = std::thread::spawn(move || {
foo_arc_2.lock().unwrap().set_bar(32);
});
foo_arc.lock().unwrap().set_bar(31);
handle.join().unwrap();
}
What I unsafely want to achieve:
struct Foo {
bar: usize,
// My own lock
// lock: std::sync::Mutex<usize>,
}
unsafe impl Sync for Foo {}
impl Foo {
pub fn set_bar(&mut self, a: usize) {
self.bar = a;
}
}
fn main() {
let mut foo = Foo { bar: 32 };
foo.bar = 33;
let foo_arc = std::sync::Arc::new(foo);
let foo_arc_2 = std::sync::Arc::clone(&foo_arc);
let handle = std::thread::spawn(move || {
foo_arc_2.set_bar(32);
});
foo_arc.set_bar(31);
handle.join().unwrap();
}
I might not have to use Arc and use something more low level unknown to me at the moment.
If you want to do this to later use it in production, don't do it! Many people smarter than you and me already done this correctly. Use what they wrote instead. If you want to do this as an exercise, or for learning purposes, then go ahead and do it.
If you want to provide a type with interior mutability then you must use UnsafeCell. This type is at a core of every interior mutability in rust and using it is the only way to get a &mut T from &T. You should read really carefully it's documentation, the documentation of the cell module and The Nomicon (preferably all of it, but at least concurrency chapter).
If you prefer watching videos, Jon Gjengset has, among many others, this amazing video on cell types. And this video on atomic memory and implementing (bad) mutex.
I'm trying to implement a method that looks like:
fn concretify<T: Any>(rc: Rc<Any>) -> Option<T> {
Rc::try_unwrap(rc).ok().and_then(|trait_object| {
let b: Box<Any> = unimplemented!();
b.downcast().ok().map(|b| *b)
})
}
However, try_unwrap doesn't work on trait objects (which makes sense, as they're unsized). My next thought was to try to find some function that unwraps Rc<Any> into Box<Any> directly. The closest thing I could find would be
if Rc::strong_count(&rc) == 1 {
Some(unsafe {
Box::from_raw(Rc::into_raw(rc))
})
} else {
None
}
However, Rc::into_raw() appears to require that the type contained in the Rc to be Sized, and I'd ideally not like to have to use unsafe blocks.
Is there any way to implement this?
Playground Link, I'm looking for an implementation of rc_to_box here.
Unfortunately, it appears that the API of Rc is lacking the necessary method to be able to get ownership of the wrapped type when it is !Sized.
The only method which may return the interior item of a Rc is Rc::try_unwrap, however it returns Result<T, Rc<T>> which requires that T be Sized.
In order to do what you wish, you would need to have a method with a signature: Rc<T> -> Result<Box<T>, Rc<T>>, which would allow T to be !Sized, and from there you could extract Box<Any> and perform the downcast call.
However, this method is impossible due to how Rc is implemented. Here is a stripped down version of Rc:
struct RcBox<T: ?Sized> {
strong: Cell<usize>,
weak: Cell<usize>,
value: T,
}
pub struct Rc<T: ?Sized> {
ptr: *mut RcBox<T>,
_marker: PhantomData<T>,
}
Therefore, the only Box you can get out of Rc<T> is Box<RcBox<T>>.
Note that the design is severely constrained here:
single-allocation mandates that all 3 elements be in a single struct
T: ?Sized mandates that T be the last field
so there is little room for improvement in general.
However, in your specific case, it is definitely possible to improve on the generic situation. It does, of course, require unsafe code. And while it works fairly well with Rc, implementing it with Arc would be complicated by the potential data-races.
Oh... and the code is provided as is, no warranty implied ;)
use std::any::Any;
use std::{cell, mem, ptr};
use std::rc::Rc;
struct RcBox<T: ?Sized> {
strong: cell::Cell<usize>,
_weak: cell::Cell<usize>,
value: T,
}
fn concretify<T: Any>(rc: Rc<Any>) -> Option<T> {
// Will be responsible for freeing the memory if there is no other weak
// pointer by the end of this function.
let _guard = Rc::downgrade(&rc);
unsafe {
let killer: &RcBox<Any> = {
let killer: *const RcBox<Any> = mem::transmute(rc);
&*killer
};
if killer.strong.get() != 1 { return None; }
// Do not forget to decrement the count if we do take ownership,
// as otherwise memory will not get released.
let result = killer.value.downcast_ref().map(|r| {
killer.strong.set(0);
ptr::read(r as *const T)
});
// Do not forget to destroy the content of the box if we did not
// take ownership
if result.is_none() {
let _: Rc<Any> = mem::transmute(killer as *const RcBox<Any>);
}
result
}
}
fn main() {
let x: Rc<Any> = Rc::new(1);
println!("{:?}", concretify::<i32>(x));
}
I don't think it's possible to implement your concretify function if you're expecting it to move the original value back out of the Rc; see this question for why.
If you're willing to return a clone, it's straightforward:
fn concretify<T: Any+Clone>(rc: Rc<Any>) -> Option<T> {
rc.downcast_ref().map(Clone::clone)
}
Here's a test:
#[derive(Debug,Clone)]
struct Foo(u32);
#[derive(Debug,Clone)]
struct Bar(i32);
fn main() {
let rc_foo: Rc<Any> = Rc::new(Foo(42));
let rc_bar: Rc<Any> = Rc::new(Bar(7));
let foo: Option<Foo> = concretify(rc_foo);
println!("Got back: {:?}", foo);
let bar: Option<Foo> = concretify(rc_bar);
println!("Got back: {:?}", bar);
}
This outputs:
Got back: Some(Foo(42))
Got back: None
Playground
If you want something more "movey", and creating your values is cheap, you could also make a dummy, use downcast_mut() instead of downcast_ref(), and then std::mem::swap with the dummy.
I'm writing a function that takes a reference to an integer and returns a vector of that integer times 2, 5 times. I think that'd look something like:
fn foo(x: &i64) -> Vec<&i64> {
let mut v = vec![];
for i in 0..5 {
let q = x * 2;
v.push(&q);
}
v
}
fn main() {
let x = 5;
let q = foo(&x);
println!("{:?}", q);
}
The borrow checker goes nuts because I define a new variable, it's allocated on the stack, and goes out of scope at the end of the function.
What do I do? Certainly I can't go through life without writing functions that create new data! I'm aware there's Box, and Copy-type workarounds, but I'm interested in an idiomatic Rust solution.
I realize I could return a Vec<i64> but I think that'd run into the same issues? Mainly trying to come up with an "emblematic" problem for the general issue :)
EDIT: I only just realized that you wrote "I'm aware there's Box, Copy etc type workaround but I'm mostly interested in an idiomatic rust solution", but I've already typed the whole answer. :P And the solutions below are idiomatic Rust, this is all just how memory works! Don't go trying to return pointers to stack-allocated data in C or C++, because even if the compiler doesn't stop you, that doesn't mean anything good will come of it. ;)
Any time that you return a reference, that reference must have been a parameter to the function. In other words, if you're returning references to data, all that data must have been allocated outside of the function. You seem to understand this, I just want to make sure it's clear. :)
There are many potential ways of solving this problem depending on what your use case is.
In this particular example, because you don't need x for anything afterward, you can just give ownership to foo without bothering with references at all:
fn foo(x: i64) -> Vec<i64> {
std::iter::repeat(x * 2).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(x));
}
But let's say that you don't want to pass ownership into foo. You could still return a vector of references as long as you didn't want to mutate the underlying value:
fn foo(x: &i64) -> Vec<&i64> {
std::iter::repeat(x).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(&x));
}
...and likewise you could mutate the underlying value as long as you didn't want to hand out new pointers to it:
fn foo(x: &mut i64) -> &mut i64 {
*x *= 2;
x
}
fn main() {
let mut x = 5;
println!("{:?}", foo(&mut x));
}
...but of course, you want to do both. So if you're allocating memory and you want to return it, then you need to do it somewhere other than the stack. One thing you can do is just stuff it on the heap, using Box:
// Just for illustration, see the next example for a better approach
fn foo(x: &i64) -> Vec<Box<i64>> {
std::iter::repeat(Box::new(x * 2)).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(&x));
}
...though with the above I just want to make sure you're aware of Box as a general means of using the heap. Truthfully, simply using a Vec means that your data will be placed on the heap, so this works:
fn foo(x: &i64) -> Vec<i64> {
std::iter::repeat(x * 2).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(&x));
}
The above is probably the most idiomatic example here, though as ever your use case might demand something different.
Alternatively, you could pull a trick from C's playbook and pre-allocate the memory outside of foo, and then pass in a reference to it:
fn foo(x: &i64, v: &mut [i64; 5]) {
for i in v {
*i = x * 2;
}
}
fn main() {
let x = 5;
let mut v = [0; 5]; // fixed-size array on the stack
foo(&x, &mut v);
println!("{:?}", v);
}
Finally, if the function must take a reference as its parameter and you must mutate the referenced data and you must copy the reference itself and you must return these copied references, then you can use Cell for this:
use std::cell::Cell;
fn foo(x: &Cell<i64>) -> Vec<&Cell<i64>> {
x.set(x.get() * 2);
std::iter::repeat(x).take(5).collect()
}
fn main() {
let x = Cell::new(5);
println!("{:?}", foo(&x));
}
Cell is both efficient and non-surprising, though note that Cell works only on types that implement the Copy trait (which all the primitive numeric types do). If your type doesn't implement Copy then you can still do this same thing with RefCell, but it imposes a slight runtime overhead and opens up the possibilities for panics at runtime if you get the "borrowing" wrong.
For example, let's say I want to access whatever value is stored at 0x0900. I found the function std::ptr::read in the Rust standard library, but the documentation isn't super clear on how to use it and I'm not sure if it's the right way.
This is what I've tried:
use std::ptr;
fn main() {
let n = ptr::read("0x0900");
println!("{}", n);
}
but it gives me error E0277
If you want to read a value of type u32 from memory location 0x0900, you could do it as follows:
use std::ptr;
fn main() {
let p = 0x0900 as *const u32;
let n = unsafe { ptr::read(p) };
println!("{}", n);
}
Note that you need to decide what type of pointer you want when casting the address to a pointer.
I have a struct which references a value (because it is ?Sized or very big). This value has to live with the struct, of course.
However, the struct shouldn't restrict the user on how to accomplish that. Whether the user wraps the value in a Box or Rc or makes it 'static, the value just has to survive with the struct. Using named lifetimes would be complicated because the reference will be moved around and may outlive our struct. What I am looking for is a general pointer type (if it exists / can exist).
How can the struct make sure the referenced value lives as long as the struct lives, without specifying how?
Example (is.gd/Is9Av6):
type CallBack = Fn(f32) -> f32;
struct Caller {
call_back: Box<CallBack>,
}
impl Caller {
fn new(call_back: Box<CallBack>) -> Caller {
Caller {call_back: call_back}
}
fn call(&self, x: f32) -> f32 {
(self.call_back)(x)
}
}
let caller = {
// func goes out of scope
let func = |x| 2.0 * x;
Caller {call_back: Box::new(func)}
};
// func survives because it is referenced through a `Box` in `caller`
let y = caller.call(1.0);
assert_eq!(y, 2.0);
Compiles, all good. But if we don't want to use a Box as a pointer to our function (one can call Box a pointer, right?), but something else, like Rc, this wont be possible, since Caller restricts the pointer to be a Box.
let caller = {
// function is used by `Caller` and `main()` => shared resource
// solution: `Rc`
let func = Rc::new(|x| 2.0 * x);
let caller = Caller {call_back: func.clone()}; // ERROR Rc != Box
// we also want to use func now
let y = func(3.0);
caller
};
// func survives because it is referenced through a `Box` in `caller`
let y = caller.call(1.0);
assert_eq!(y, 2.0);
(is.gd/qUkAvZ)
Possible solution: Deref? (http://is.gd/mmY6QC)
use std::rc::Rc;
use std::ops::Deref;
type CallBack = Fn(f32) -> f32;
struct Caller<T>
where T: Deref<Target = Box<CallBack>> {
call_back: T,
}
impl<T> Caller<T>
where T: Deref<Target = Box<CallBack>> {
fn new(call_back: T) -> Caller<T> {
Caller {call_back: call_back}
}
fn call(&self, x: f32) -> f32 {
(*self.call_back)(x)
}
}
fn main() {
let caller = {
// function is used by `Caller` and `main()` => shared resource
// solution: `Rc`
let func_obj = Box::new(|x: f32| 2.0 * x) as Box<CallBack>;
let func = Rc::new(func_obj);
let caller = Caller::new(func.clone());
// we also want to use func now
let y = func(3.0);
caller
};
// func survives because it is referenced through a `Box` in `caller`
let y = caller.call(1.0);
assert_eq!(y, 2.0);
}
Is this the way to go with Rust? Using Deref? It works at least.
Am I missing something obvious?
This question did not solve my problem, since the value is practically unusable as a T.
While Deref provides the necessary functionality, AsRef and Borrow are more appropriate for this situation (Borrow more so than AsRef in the case of a struct). Both of these traits let your users use Box<T>, Rc<T> and Arc<T>, and Borrow also lets them use &T and T. Your Caller struct could be written like this:
use std::borrow::Borrow;
struct Caller<CB: Borrow<Callback>> {
callback: CB,
}
Then, when you want to use the callback field, you need to call the borrow() (or as_ref()) method:
impl<CB> Caller<CB>
where CB: Borrow<Callback>
{
fn new(callback: CB) -> Caller<CB> {
Caller { callback: callback }
}
fn call(&self, x: f32) -> f32 {
(self.callback.borrow())(x)
}
}
It crashes with the current stable compiler (1.1), but not with beta or nightly (just use your last Playpen link and change the "Channel" setting at the top). I believe that support for Rc<Trait> was only partial in 1.1; there were some changes that didn't make it in time. This is probably why your code doesn't work.
To address the question of using Deref for this... if dereferencing the pointer is all you need... sure. It's really just a question of whether or not the trait(s) you've chosen support the operations you need. If yes, great.
As an aside, you can always write a new trait that expresses the exact semantics you need, and implement that for existing types. From what you've said, it doesn't seem necessary in this case.