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,
T
se puede reemplazar conBox<T>
-
Use
AtomicT
cuandoT
es unbool
o 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
:Cell
yRefCell
-
Los contenedores contados por referencia, como
Rc
yArc
. -
Los tipos en el
módulo
std::sync
:Mutex
oAtomicBool
por 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 T
para 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
:
-
Cell
evita la formación de referencias a su interior, evitando referencias colgantes, -
RefCell
cambia 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:
-
AtomicXXX
son soloCell
: no hace referencia al interior, solo se mueve hacia adentro / afuera, -
RwLock
es soloRefCell
: puede obtener referencias al interior a través de guardias , -
Mutex
es una versión simplificada deRwLock
que no distingue entre un protector de solo lectura y un protector de escritura; conceptualmente similar a unRefCell
con solo un métodoborrow_mut
.
Si vienes de un fondo C ++:
-
Box
esunique_ptr
, -
Arc
esshared_ptr
, -
Rc
es una versión no segura deshared_ptr
deshared_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).