[英]Is it undefined behavior to dereference a *mut T cast to *mut ManuallyDrop<T>?
[英]Cast &self to mut (to use predefined trait where it isn't mut)
我正在嘗試實現分配器:
pub unsafe trait Allocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
...
請注意, &self 是不可變的。 我不確定哪種分配器能夠在不更改分配器本身的情況下進行分配,但這是vec
准備與之交談的,所以我想我必須忍受它。 我的問題是:
我試着在 impl 中加入 mut:
unsafe impl Allocator for Mappoc {
fn allocate(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
...
但它說:
|| error[E0053]: method `allocate` has an incompatible type for trait
src/lib.rs|110| 17
|| |
|| 110 | fn allocate(&mut self, layout: Layout)
|| | ^^^^^^^^^
|| | |
|| | types differ in mutability
|| | help: change the self-receiver type to match the trait: `self: &Mappoc`
|| |
|| = note: expected fn pointer `fn(&Mappoc, std::alloc::Layout) -> Result<_, _>`
|| found fn pointer `fn(&mut Mappoc, std::alloc::Layout) -> Result<_, _>`
簡而言之, allocate()
采用&self
以允許從多個線程中使用分配器。 (請記住, &mut
引用是獨占的,一次只能存在一個。)從不可變引用中獲取可變引用的最簡單的線程安全方法是將實際分配器包裝在互斥體中:
struct MappocAllocator {
inner: Mutex<Mappoc>, // your actual allocator
}
impl Allocator for MappocAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let alloc = self.inner.lock().unwrap();
// now you have access to `&mut Mappoc` for the duration of the lock
...
}
}
我不確定在不對分配器本身進行更改的情況下能夠分配哪種分配器
這是對&T
含義的誤解。 共享引用並不總是意味着它下面的數據不會改變,這意味着多個參與者一次使用它是安全的。 例如,無鎖變異 API 總是采用&self
。
如果您實際使用的分配器是用 Rust 編寫的並且本身是線程安全的(或部分/完全無鎖),那么它的方法應該以&self
開頭,並且您不需要互斥鎖(因為互斥鎖或其等價物將成為Mappoc
實現的一部分)。 如果Mappoc
的方法采用&mut self
,則意味着從多個線程調用它們是不安全的,Rust 強制您通過互斥體訪問它們是一件好事。 這是完全按照設計工作的系統。
最后,一些分配器,如mimalloc
或jemalloc
,在 C 或 C++ 中實現,它們自己鎖定。 但是他們的 Rust 前端也不需要&mut self
因為它們通過原始指針調用實際的分配器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.