Strange behavior: Writing to a pointer or not doesn't affect the outcome

Again, thanks for your answer, as mentioned above I have some follow-up questions or remarks.

Multiple &mut references

As far as I understood it, I should most certainly don't take a mutable reference to the slice in the slot_allocator but a pointer (and not using a slice in the allocator at all).

  1. My question is, when I create the pin in:

but later use the pinned future to poll it, should I better use a pointer here as well, since I later need a mutable reference when I poll the future?

Usage of Pin in the slot allocator

I did not know, that [u8] is Unpin, so thanks for pointing this out. And therefore it makes no sense to Pin the slice. My line of thinking was, since I need a Pin on the futures that I store in the slice, I should Pin the slice, so that the elements I allocate into this slice can rely on the fact that the slice is pinned. This obviously doesn't work since a slice is Unpin.

  1. My question is: Should the allocator contain a Pin on the pointer it is working with. This means that SlotAllocator looks something like:
struct SlotAllocator {
     memory: Pin<* mut u8>,
     // ...
}

Or is this useless as well?

Padding for T

I create the pointer with respect to the alignment of and size of type T. (see src/slot_allocator.rs · main · huntrss / aeons · GitLab). The size is "just" used to check that I don't override. If a type is two large, the allocation fails.

  1. My question is: Regarding the padding of the fields of a type. You mean especially this line, that copies the uninitialized T here: src/slot_box.rs · main · huntrss / aeons · GitLab. Or a different part of the code?

You can technically use a raw slice *mut [u8], but the len method on raw slices is still unstable, which makes them pretty unusable in practice. So yes, *mut u8 is your best option for now.

I think not. This is the best place to ensure that the reference is indeed unique, provided that you properly implement resource semantics for the SlotBox (i.e. the memory is exclusively owned by SlotBox for as long as it lives, and is deallocated on drop). If you use a raw pointer here, you'll need to insert extra unsafe code at future poll site, but at that point you have no way to know that the aliasing and liveness guarantees are satisfied (apart from backtracking through the whole program up to this specific point).

Pretty much everything which isn't a self-referential structure is Unpin, unless the type's author went out of their way to make it !Unpin for API evolution or other reasons. Unpin is an auto trait, which makes it automatically implemented for any struct or enum which has all fields Unpin, as well as for slices and arrays of Unpin types.

In practice, the most common source of !Unpin types are futures, but even among those not all are !Unpin. Futures which don't need to store self-references are often declared Unpin.

Data which is behind a reference is always pinned for the lifetime of that reference, in the sense that the memory region won't change and will be live while the reference is live. So you don't need to worry that the memory region will be accidentally moved from under you (unless someone messes up in unsafe code). Pin exists to ensure that you don't accidentally modify the pointee in a way which can violate self-references (e.g. blindly copy/move the object behind the pointer to a new location). Since Pin<&mut T> is a distinct type from &mut T, you can no longer apply the usual methods which work on &mut T to this type. Instead, you need to only use methods which explicitly acknowledge the possible self-referentiality of T by using unsafe code to work with Pin<&mut T> (or delegate to other such methods). If T: !Unpin, all of that is irrelevant, and you can safely pass between pinned and non-pinned pointers.

Considering the above, no.

I don't see how your comment is related to mine. Have you read the reference on type layout? By the way, Layout is a stable type, so consider using it in your allocator. While the Allocator trait is unstable, the GlobalAlloc trait is stable, and both describe roughly the interface that people expect from the allocator.

Yes. There may be other such code, I haven't checked exhaustively.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.