diff options
author | Ahson Khan <ahkha@microsoft.com> | 2018-03-27 17:05:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-27 17:05:33 -0700 |
commit | 0578152ed085597fd5e7f35e63ac2b9b4a5a7f28 (patch) | |
tree | dc1eee5480cff8ba1977fb2e038b8ccccb4c2145 /src/mscorlib/shared | |
parent | 65bf37cbbb7290c9f52402fa380b1d3a8dae6b83 (diff) | |
download | coreclr-0578152ed085597fd5e7f35e63ac2b9b4a5a7f28.tar.gz coreclr-0578152ed085597fd5e7f35e63ac2b9b4a5a7f28.tar.bz2 coreclr-0578152ed085597fd5e7f35e63ac2b9b4a5a7f28.zip |
Adding Memory.Pin() to eventually replace Memory.Retain(bool) (#17269)
* Adding Memory.Pin() to eventually replace Memory.Retain(bool)
* Fix copy/paste error and return default for when object is null.
* Fix XML comments.
Diffstat (limited to 'src/mscorlib/shared')
-rw-r--r-- | src/mscorlib/shared/System/Memory.cs | 44 | ||||
-rw-r--r-- | src/mscorlib/shared/System/ReadOnlyMemory.cs | 38 |
2 files changed, 78 insertions, 4 deletions
diff --git a/src/mscorlib/shared/System/Memory.cs b/src/mscorlib/shared/System/Memory.cs index 508ebcb3ee..bb2b1557a9 100644 --- a/src/mscorlib/shared/System/Memory.cs +++ b/src/mscorlib/shared/System/Memory.cs @@ -270,9 +270,49 @@ namespace System 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() + { + 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; diff --git a/src/mscorlib/shared/System/ReadOnlyMemory.cs b/src/mscorlib/shared/System/ReadOnlyMemory.cs index 5f3f0e1980..dca7db3dfd 100644 --- a/src/mscorlib/shared/System/ReadOnlyMemory.cs +++ b/src/mscorlib/shared/System/ReadOnlyMemory.cs @@ -226,10 +226,44 @@ namespace System /// <param name="destination">The span to copy items into.</param> public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span); - /// <summary>Creates a handle for the memory.</summary> + /// <summary> + /// 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() + { + if (_index < 0) + { + return ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>()); + } + else if (typeof(T) == typeof(char) && _object is string s) + { + 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 the memory's address can be taken and used. + /// is disposed, enabling taking and using the memory's address. /// </param> public unsafe MemoryHandle Retain(bool pin = false) { |