This repository was archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Adding Memory.Pin() to eventually replace Memory.Retain(bool) #17269
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -270,9 +270,49 @@ public Span<T> Span | |
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span); | ||
|
||
/// <summary> | ||
/// Returns a handle for the array. | ||
/// <param name="pin">If pin is true, the GC will not move the array and hence its address can be taken</param> | ||
/// Creates a handle for the memory. | ||
/// The GC will not move the array until the returned <see cref="MemoryHandle"/> | ||
/// is disposed, enabling taking and using the memory's address. | ||
/// </summary> | ||
public unsafe MemoryHandle Pin() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we prefer the whole method to be unsafe, or just the part that does pointer arithmetic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept the changes from Retain minimal. Also, we would end up with two unsafe blocks if we want to make this change (within each condition), which doesn't buy us much. Otherwise, it would be around the entire if block, which is essentially equivalent to it being around the whole method. |
||
{ | ||
if (_index < 0) | ||
{ | ||
return ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>()); | ||
} | ||
else if (typeof(T) == typeof(char) && _object is string s) | ||
{ | ||
// This case can only happen if a ReadOnlyMemory<char> was created around a string | ||
// and then that was cast to a Memory<char> using unsafe / marshaling code. This needs | ||
// to work, however, so that code that uses a single Memory<char> field to store either | ||
// a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and | ||
// used for interop purposes. | ||
GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned); | ||
#if FEATURE_PORTABLE_SPAN | ||
void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index); | ||
#else | ||
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index); | ||
#endif // FEATURE_PORTABLE_SPAN | ||
return new MemoryHandle(null, pointer, handle); | ||
} | ||
else if (_object is T[] array) | ||
{ | ||
var handle = GCHandle.Alloc(array, GCHandleType.Pinned); | ||
#if FEATURE_PORTABLE_SPAN | ||
void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index); | ||
#else | ||
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index); | ||
#endif // FEATURE_PORTABLE_SPAN | ||
return new MemoryHandle(null, pointer, handle); | ||
} | ||
return default; | ||
} | ||
|
||
/// <summary>[Obsolete, use Pin()] Creates a handle for the memory.</summary> | ||
/// <param name="pin"> | ||
/// If pin is true, the GC will not move the array until the returned <see cref="MemoryHandle"/> | ||
/// is disposed, enabling taking and using the memory's address. | ||
/// </param> | ||
public unsafe MemoryHandle Retain(bool pin = false) | ||
{ | ||
MemoryHandle memoryHandle = default; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc comment should not talk about arrays. In the OwnedMemory more there might not be an array.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. The docs should also mention the possibility of GCHandle.Alloc throwing (An instance with nonprimitive (non-blittable) members cannot be pinned.).
I will address this separately after all the changes are in.