最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

rust - How can I make multiple copies of a slice, to use in different threads? - Stack Overflow

programmeradmin4浏览0评论

I have some memory:

let mut storage = [0u128; 256];
let storage_ref = &mut storage;

I want to make multiple copies of storage_ref, so that I can carefully mutate the u128s within storage, using cmpxchg16b in different threads. This will need to make use of unsafe.

What is the syntax for making multiple copies of the storage_ref (both pointer and size, to pass to the various threads)?

I have some memory:

let mut storage = [0u128; 256];
let storage_ref = &mut storage;

I want to make multiple copies of storage_ref, so that I can carefully mutate the u128s within storage, using cmpxchg16b in different threads. This will need to make use of unsafe.

What is the syntax for making multiple copies of the storage_ref (both pointer and size, to pass to the various threads)?

Share Improve this question asked Feb 15 at 16:42 fadedbeefadedbee 44.8k48 gold badges199 silver badges349 bronze badges 9
  • 2 You cannot have overlapping mutable references, period. You can have overlapping raw pointers, but you need to be careful with how you create them. – Chayim Friedman Commented Feb 15 at 16:46
  • @ChayimFriedman So what I need to copy is a pointer to the start of the storage and the length of the storage? I can then add offsets to the pointer and dereference it in unsafe blocks? – fadedbee Commented Feb 15 at 16:49
  • No, you don't dereference it. If you dereference it then again it cannot overlap with other pointers. – Chayim Friedman Commented Feb 15 at 16:54
  • @ChayimFriedman If the OP adds offset first and then dereferences, though, that should be fine, as long as different threads don't operate on overlapping data, right? – user4815162342 Commented Feb 15 at 18:12
  • 1 Since you're calling an atomic primitive, another option is to use [UnsafeCell<u128>; 256]. You can extract mut pointer from a non-mut cell, so you'll have no problems with the borrow checker. – user4815162342 Commented Feb 15 at 18:27
 |  Show 4 more comments

1 Answer 1

Reset to default 1

To achieve this, you must convert the unique reference &mut [u128; 256] into a raw pointer *mut [u128; 256], which can be done using a coercion:

let storage_ptr: *mut [u128; 256] = storage_ref;

Or, it can be done by constructing a raw pointer in the first place:

let storage_ptr: *mut [u128; 256] = &raw mut storage;

You must do this exactly once (not once per thread), and then you are free to distribute the pointer to many threads.

Since you intend to use atomic operations, you won’t be causing data races, which is necessary — data races are UB regardless of whether you use references or raw pointers. You do need to make sure to stop using the raw pointers before any other mutable reference is taken to storage.


You should also consider, instead of using unsafe and assembly code, using [std::sync::atomic::AtomicU128; 256], which allows atomic operations from safe code. (This type only exists on platforms which support 128-bit atomic operations, but that should work anywhere your assembly code would work.)

发布评论

评论列表(0)

  1. 暂无评论