cell
Cell
Cell是什么东西
#[repr(transparent)]
pub struct Cell<T: ?Sized> {
value: UnsafeCell<T>,
}
impl<T> Cell<T> {
pub const fn new(value: T) -> Cell<T> {
Cell {
value: UnsafeCell::new(value),
}
}
pub fn set(&self, val: T) {
let old = self.replace(val);
drop(old);
}
}
Cell的set方法只要求拥有不可变的reference 这就是她最大的作用
有什么用 或者说在实际的例子中人们是怎么使用Cell的
假设我们希望不用mut ref 一个struct 来mut一个struct
use std::cell::Cell;
struct SomeStruct {
regular_field: u8,
special_field: Cell<u8>,
}
let my_struct = SomeStruct {
regular_field: 0,
special_field: Cell::new(1),
};
let new_value = 100;
// ERROR, because my_struct is immutable
// my_struct.regular_field = new_value;
// WORKS, although `my_struct` is immutable, field `special_field` is mutable because it is Cell
my_struct.special_field.set(new_value);
assert_eq!(my_struct.special_field.get(), new_value);
希望做一些兼容性的操作
or because you must employ mutation to implement a trait method that was originally defined to take &self.
偷偷的进行mut 理论上不用mut的地方在实现上需要mut
-
例如实现memorize 每次只是get(&self) 但实际上要修改缓存(&mut self)
use std::cell::RefCell;
struct Graph { edges: Vec<(i32, i32)>, spantreecache: RefCell<Option<Vec<(i32, i32)>>> }
impl Graph { fn minimumspanningtree(&self) -> Vec<(i32, i32)> { // Create a new scope to contain the lifetime of the // dynamic borrow { // Take a reference to the inside of cache cell let mut cache = self.spantreecache.borrowmut(); if cache.issome() { return cache.as_ref().unwrap().clone(); }
let span_tree = self.calc_span_tree();
*cache = Some(span_tree);
}
// Recursive call to return the just-cached value.
// Note that if we had not let the previous borrow
// of the cache fall out of scope then the subsequent
// recursive borrow would cause a dynamic thread panic.
// This is the major hazard of using `RefCell`.
self.minimum_spanning_tree()
}
}
2. 例如引用计数在clone(&self)时要增加count(&mut self)
```rust
#![feature(core_intrinsics)]
use std::cell::Cell;
use std::ptr::NonNull;
use std::intrinsics::abort;
struct Rc<T: ?Sized> {
ptr: NonNull<RcBox<T>>
}
struct RcBox<T: ?Sized> {
strong: Cell<usize>,
refcount: Cell<usize>,
value: T,
}
impl<T: ?Sized> Clone for Rc<T> {
fn clone(&self) -> Rc<T> {
self.inc_strong();
Rc { ptr: self.ptr }
}
}
trait RcBoxPtr<T: ?Sized> {
fn inner(&self) -> &RcBox<T>;
fn strong(&self) -> usize {
self.inner().strong.get()
}
fn inc_strong(&self) {
self.inner()
.strong
.set(self.strong()
.checked_add(1)
.unwrap_or_else(|| unsafe { abort() }));
}
}
impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
fn inner(&self) -> &RcBox<T> {
unsafe {
self.ptr.as_ref()
}
}
}
当我们有某个共有的变量 同时有多个struct希望能够修改她
struct A<'a>(&'a mut i32);
impl<'a> A<'a> {
fn change_to(&mut self, v: i32) {
*self.0 = v;
}
}
fn main() {
let mut x = 10;
let mut a = A(&mut x);
let mut b = A(&mut x);
a.change_to(2);
// b.change_to(1);
println!("{:?}",x);
}
// use std::cell::Cell;
// struct A<'a>(&'a Cell::<i32>);
// impl<'a> A<'a> {
// fn change_to(&self,v:i32){
// self.0.set(v);
// }
// }
// fn main() {
// let x = Cell::new(10);
// let a = A(&x);
// let b = A(&x);
// b.change_to(1);
// a.change_to(2);
// println!("{:?}",x);
// }