Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Mirror changes from dotnet/corefx #15909

Merged
merged 4 commits into from
Jan 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 30 additions & 27 deletions src/mscorlib/Resources/Strings.resx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema

Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
Expand All @@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple

There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
Expand Down Expand Up @@ -2866,6 +2866,9 @@
<data name="Marshaler_StringTooLong" xml:space="preserve">
<value>Marshaler restriction: Excessively long string.</value>
</data>
<data name="MemoryDisposed" xml:space="preserve">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string is redundant with Memory_ThrowIfDisposed.

<value>Memory&lt;T&gt; has been disposed.</value>
</data>
<data name="MissingConstructor_Name" xml:space="preserve">
<value>Constructor on type '{0}' not found.</value>
</data>
Expand Down
11 changes: 11 additions & 0 deletions src/mscorlib/shared/System/Buffers/IRetainable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,20 @@

namespace System.Buffers
{
/// <summary>
/// Provides a mechanism for manual lifetime management.
/// </summary>
public interface IRetainable
{
/// <summary>
/// Call this method to indicate that the IRetainable object is in use.
/// Do not dispose until Release is called.
/// </summary>
void Retain();
/// <summary>
/// Call this method to indicate that the IRetainable object is no longer in use.
/// The object can now be disposed.
/// </summary>
bool Release();
}
}
56 changes: 40 additions & 16 deletions src/mscorlib/shared/System/Buffers/MemoryHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,46 @@

namespace System.Buffers
{
/// <summary>
/// A handle for the memory.
/// </summary>
public unsafe struct MemoryHandle : IDisposable
{
private IRetainable _owner;
private IRetainable _retainable;
private void* _pointer;
private GCHandle _handle;

/// <summary>
/// Creates a new memory handle for the memory.
/// </summary>
/// <param name="retainable">reference to manually managed object</param>
/// <param name="pointer">pointer to memory, or null if a pointer was not provided when the handle was created</param>
/// <param name="handle">handle used to pin array buffers</param>
[CLSCompliant(false)]
public MemoryHandle(IRetainable owner, void* pointer = null, GCHandle handle = default(GCHandle))
public MemoryHandle(IRetainable retainable, void* pointer = null, GCHandle handle = default(GCHandle))
{
_owner = owner;
_retainable = retainable;
_pointer = pointer;
_handle = handle;
}

/// <summary>
/// Returns the pointer to memory, or null if a pointer was not provided when the handle was created.
/// </summary>
[CLSCompliant(false)]
public void* Pointer => _pointer;

/// <summary>
/// Returns false if the pointer to memory is null.
/// </summary>
public bool HasPointer => _pointer != null;

/// <summary>
/// Adds an offset to the pinned pointer.
/// </summary>
/// <exception cref="System.ArgumentNullException">
/// Throw when pinned pointer is null.
/// </exception>
internal void AddOffset(int offset)
{
if (_pointer == null)
Expand All @@ -33,26 +59,24 @@ internal void AddOffset(int offset)
}
}

[CLSCompliant(false)]
public void* Pointer => _pointer;

public bool HasPointer => _pointer != null;

public void Dispose()
{
if (_handle.IsAllocated)
/// <summary>
/// Frees the pinned handle and releases IRetainable.
/// </summary>
public void Dispose()
{
if (_handle.IsAllocated)
{
_handle.Free();
}

if (_owner != null)
if (_retainable != null)
{
_owner.Release();
_owner = null;
_retainable.Release();
_retainable = null;
}

_pointer = null;
_pointer = null;
}

}
}
52 changes: 47 additions & 5 deletions src/mscorlib/shared/System/Buffers/OwnedMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,88 @@

namespace System.Buffers
{
/// <summary>
/// Owner of Memory<typeparamref name="T"/> that provides appropriate lifetime management mechanisms for it.
/// </summary>
public abstract class OwnedMemory<T> : IDisposable, IRetainable
{
/// <summary>
/// The number of items in the Memory<typeparamref name="T"/>.
/// </summary>
public abstract int Length { get; }

/// <summary>
/// Returns a span wrapping the underlying memory.
/// </summary>
public abstract Span<T> Span { get; }

/// <summary>
/// Returns a Memory<typeparamref name="T"/> if the underlying memory has not been freed.
/// </summary>
/// <exception cref="System.ObjectDisposedException">
/// Thrown when the underlying memory has already been disposed.
/// </exception>
public Memory<T> Memory
{
get
get
{
if (IsDisposed)
if (IsDisposed)
{
ThrowHelper.ThrowObjectDisposedException(nameof(OwnedMemory<T>), ExceptionResource.Memory_ThrowIfDisposed);
ThrowHelper.ThrowObjectDisposedException_MemoryDisposed();
}
return new Memory<T>(owner: this, 0, Length);
}
}

/// <summary>
/// Returns a handle for the array that has been pinned and hence its address can be taken
/// </summary>
public abstract MemoryHandle Pin();

/// <summary>
/// Returns an array segment.
/// </summary>
protected internal abstract bool TryGetArray(out ArraySegment<T> arraySegment);

/// <summary>
/// Implements IDisposable.
/// </summary>
/// <exception cref="System.InvalidOperationException">
/// Throw when there are still retained references to the memory
/// </exception>
public void Dispose()
{
if (IsRetained)
if (IsRetained)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Memory_OutstandingReferences);
ThrowHelper.ThrowInvalidOperationException_OutstandingReferences();
}
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Clean up of any leftover managed and unmanaged resources.
/// </summary>
protected abstract void Dispose(bool disposing);

/// <summary>
/// Return true if someone is holding a reference to the memory.
/// </summary>
protected abstract bool IsRetained { get; }

/// <summary>
/// Return true if the underlying memory has been freed.
/// </summary>
public abstract bool IsDisposed { get; }

/// <summary>
/// Implements IRetainable. Prevent accidental disposal of the memory.
/// </summary>
public abstract void Retain();

/// <summary>
/// Implements IRetainable. The memory can now be diposed.
/// </summary>
public abstract bool Release();

}
Expand Down
Loading