Rust標準ライブラリにはいくつかのラッパータイプがあります。
std::cell
module : Cell
および RefCell
Rc
や Arc
などの参照カウントラッパー。std::sync
module : Mutex
または AtomicBool
など私が理解しているように、これらはラッパーであり、単純な参照よりもさらなる可能性を提供します。いくつかの基本を理解していますが、全体像を見ることができません。
彼らは正確に何をしますか?セルと参照カウントファミリは、直交または類似の機能を提供しますか?
Rustには2つの基本的な概念があります。
さまざまなポインタータイプ(Box
、Rc
、Arc
)はOwnershipに関係しています。単一のオブジェクトの所有者が単一か複数かを制御できます。
一方、さまざまなセル(Cell
、RefCell
、Mutex
、RwLock
、AtomicXXX
)は可変性。
Rustの安全性の基礎となるルールは、Aliasing XOR Mutabilityです。つまり、オブジェクトは、その内部への顕著な参照がない場合にのみ安全に変更できます。
このルールは通常、コンパイル時に借用チェッカーによって実施されます。
&T
がある場合、スコープ内の同じオブジェクトに対して&mut T
を使用することはできません。&mut T
がある場合、スコープ内の同じオブジェクトへの参照もできません。ただし、これには十分な柔軟性がない場合があります。時には、同じオブジェクトへの複数の参照を持ちながら、それを変更する機能が必要な(または必要な)場合があります。 cellsを入力します。
Cell
とRefCell
の考え方は、エイリアスの存在下で、制御された方法で可変性を許可することです。
Cell
は、内部への参照の形成を防ぎ、ぶら下がり参照を回避します。RefCell
は、コンパイル時からランタイムにAliasing XOR Mutabilityの強制を変更します。この機能は、interior mutabilityを提供すると説明される場合があります。これは、外部からは不変に見えるオブジェクト(&T
)を実際に変更できる場所です。
この可変性が複数のスレッドにまたがる場合、代わりにMutex
、RwLock
またはAtomicXXX
;を使用します。それらは同じ機能を提供します:
AtomicXXX
は単なるCell
です。内部への参照はなく、単に出入りします。RwLock
はRefCell
だけです:guardsを介して内部への参照を取得できます。Mutex
はRwLock
の簡易バージョンであり、読み取り専用ガードと書き込みガードを区別しません。 borrow_mut
メソッドのみを持つRefCell
に概念的に似ています。C++のバックグラウンドから来た場合:
Box
はunique_ptr
です、Arc
はshared_ptr
です、Rc
は、shared_ptr
の非スレッドセーフバージョンです。また、セルはmutable
と同様の機能を提供しますが、エイリアスの問題を回避するための追加の保証があります。 Cell
をstd::atomic
と見なし、RefCell
をstd::shared_mutex
のスレッドセーフでないバージョンと見なします(ロックが取得されると、ブロックする代わりにスローされます)。
Matthieuの良い答え のおかげで、必要なラッパーを見つけるのに役立つ図を以下に示します。
+-----------+
| 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>> |
+================+
T
はBox<T>
に置き換えることができますAtomicT
T
がbool
または数値の場合Mutex
とRwLock
のどちらを使用すべきかを知るには、 この関連する質問 を参照してください。