ps4 - Necesita una explicación holística sobre la celda de Rust y los tipos contados de referencia
rust traduccion (2)
Gracias a la buena respuesta de Matthieu , aquí hay un diagrama para ayudar a las personas a encontrar el envoltorio que necesitan:
+-----------+
| Ownership |
+--+--------+ +================+
| +-Static----->| T |(1)
| | +================+
| |
| | +================+
| +-----------+ | Local Val| Cell<T> |(1)
+-Unique-->| Borrowing +--+-Dynamic---->|----------------|
| +-----------+ | Ref| RefCell<T> |(1)
| | +================+
| |
| | +================+
| | Threaded | AtomicT |(2)
| +-Dynamic---->|----------------|
| | Mutex<T> |(1)
| | RwLock<T> |(1)
| +================+
|
|
| +================+
| +-No--------->| Rc<T> |
| | +================+
| Locally +-----------+ |
+-Shared-->| Mutable? +--+ +================+
| +-----------+ | Val| Rc<Cell<T>> |
| +-Yes-------->|----------------|
| Ref| Rc<RefCell<T>> |
| +================+
|
|
| +================+
| +-No--------->| Arc<T> |
| | +================+
| Shared +-----------+ |
+-Between->| Mutable? +--+ +================+
Threads +-----------+ | | Arc<AtomicT> |(2)
+-Yes-------->|----------------|
| Arc<Mutex<T>> |
| Arc<RwLock<T>> |
+================+
-
En esos casos,
Tse puede reemplazar conBox<T> -
Use
AtomicTcuandoTes unboolo un número
Para saber si debe usar
Mutex
o
RwLock
, consulte
esta pregunta relacionada
.
Hay varios tipos de envoltorios en la biblioteca estándar de Rust:
-
Las celdas en el
módulo
std::cell:CellyRefCell -
Los contenedores contados por referencia, como
RcyArc. -
Los tipos en el
módulo
std::sync:MutexoAtomicBoolpor ejemplo
Según tengo entendido, estos son envoltorios que ofrecen más posibilidades que una simple referencia. Si bien entiendo algunos conceptos básicos, no puedo ver la imagen completa.
¿Qué hacen exactamente? ¿Las celdas y las familias contadas por referencia proporcionan características ortogonales o similares?
Hay dos conceptos esenciales en Rust:
- Propiedad,
- Mutabilidad.
Los diversos tipos de puntero (
Box
,
Rc
,
Arc
) están relacionados con la
propiedad
: permiten controlar si hay un único propietario o varios propietarios para un solo objeto.
Por otro lado, las diversas células (
Cell
,
RefCell
,
Mutex
,
RwLock
,
AtomicXXX
) están relacionadas con la
mutabilidad
.
La regla fundamental de la seguridad de Rust es Aliasing XOR Mutability . Es decir, un objeto solo puede mutarse de forma segura si no hay una referencia destacada a su interior.
Esta regla generalmente se aplica en tiempo de compilación por el verificador de préstamos :
-
si tiene un
&T, tampoco puede tener un&mut Tpara el mismo objeto en alcance, -
si tiene un
&mut T, tampoco puede tener ninguna referencia al mismo objeto en su alcance.
Sin embargo, a veces, esto no es lo suficientemente flexible. A veces, usted necesita (o quiere) la capacidad de tener múltiples referencias al mismo objeto y, sin embargo, mutarlo. Ingresa las celdas .
La idea de
Cell
y
RefCell
es permitir la mutabilidad en presencia de alias
de manera controlada
:
-
Cellevita la formación de referencias a su interior, evitando referencias colgantes, -
RefCellcambia la aplicación de Aliasing XOR Mutability del tiempo de compilación al tiempo de ejecución.
Esta funcionalidad a veces se describe como una capacidad de mutación
interior
, que es donde un objeto que de otro modo parece inmutable desde el exterior (
&T
) puede en realidad mutarse.
Cuando esta mutabilidad se extiende a través de múltiples subprocesos, en su lugar usará
Mutex
,
RwLock
o
AtomicXXX
;
Proporcionan la misma funcionalidad:
-
AtomicXXXson soloCell: no hace referencia al interior, solo se mueve hacia adentro / afuera, -
RwLockes soloRefCell: puede obtener referencias al interior a través de guardias , -
Mutexes una versión simplificada deRwLockque no distingue entre un protector de solo lectura y un protector de escritura; conceptualmente similar a unRefCellcon solo un métodoborrow_mut.
Si vienes de un fondo C ++:
-
Boxesunique_ptr, -
Arcesshared_ptr, -
Rces una versión no segura deshared_ptrdeshared_ptr.
Y las celdas proporcionan una funcionalidad similar a la de
mutable
, excepto con garantías adicionales para evitar problemas de aliasing;
piense en
Cell
como
std::atomic
y
RefCell
como una versión no segura para subprocesos de
std::shared_mutex
(que arroja en lugar de bloquear si se
std::shared_mutex
el bloqueo).