Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API Proposal]: IReadOnlyMemoryOwner<T> to indicate buffer ownership and provide read-only access #110947

Open
scharnyw opened this issue Dec 26, 2024 · 5 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Memory untriaged New issue has not been triaged by the area owner

Comments

@scharnyw
Copy link
Contributor

scharnyw commented Dec 26, 2024

Background and motivation

Both Span<T> and Memory<T> have read-only counterparts (ReadOnlySpan<T> and ReadOnlyMemory<T>) to provide read-only access but IMemoryOwner<T> currently does not.

When using IMemoryOwner<T> it is quite often that we need to transfer ownership (i.e. responsibility to dispose) and read access, but we do not intend to give the recipient write capabilities. For example, buffer could be transferred from a data producing class to a data consuming class, the latter is expected to be only reading the data and disposing of it at the end of its consumption. In such cases an IReadOnlyMemoryOwner<T> interface which provides access to a ReadOnlyMemory<T> will better document the purpose and prevent misuse.

API Proposal

namespace System.Buffers;

public interface IReadOnlyMemoryOwner<T> : IDisposable
{
    ReadOnlyMemory<T> Memory { get; }
}

public interface IMemoryOwner<T> : IReadOnlyMemoryOwner<T>
{
    new Memory<T> Memory { get; }

    // default interface implementation
    ReadOnlyMemory<T> IReadOnlyMemoryOwner<T>.Memory => Memory;
}

API Usage

var buffer = MemoryPool<T>.Shared.Rent();

// populate buffer with data

new DataConsumer().ConsumeData(buffer);

public class DataConsumer
{
    // data consumer should accept `IReadOnlyMemoryOwner<T>` to accept ownership and read-only access to the data
    public void ConsumeData(IReadOnlyMemoryOwner<T> buffer)
    {
        // work with buffer.Memory
    }
}

Alternative Designs

No response

Risks

No response

@scharnyw scharnyw added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Dec 26, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Dec 26, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-memory
See info in area-owners.md if you want to be subscribed.

@colejohnson66
Copy link

Why not just take a ReadOnlyMemory?

var buffer = MemoryPool<T>.Shared.Rent();

// populate buffer with data

new DataConsumer().ConsumeData(buffer.Memory);

public class DataConsumer
{
    public void ConsumeData(ReadOnlyMemory<T> buffer)
    {
        // work with buffer
    }
}

@scharnyw
Copy link
Contributor Author

Why not just take a ReadOnlyMemory?

ReadOnlyMemory does not own the underlying storage. For example if DataConsumer needs to store the buffer for further processing, it would not be able to dispose of the storage (e.g. return memory to memory pool, free underlying unmanaged memory, or whatever) at the end of usage if it takes a ReadOnlyMemory.

@teo-tsirpanis
Copy link
Contributor

transfer ownership (i.e. responsibility to dispose) and read access, but we do not intend to give the recipient write capabilities

This restriction does not sound right; the "owner" of a resource should be able to do anything with it. Scenarios where a memory owner is actually unable to write to it revolve around unmanaged memory, for which UnmanagedMemoryAccessor provides a better abstraction, and you can create a ReadOnlyMemory<T> around it if you want.

@scharnyw
Copy link
Contributor Author

transfer ownership (i.e. responsibility to dispose) and read access, but we do not intend to give the recipient write capabilities

This restriction does not sound right; the "owner" of a resource should be able to do anything with it. Scenarios where a memory owner is actually unable to write to it revolve around unmanaged memory, for which UnmanagedMemoryAccessor provides a better abstraction, and you can create a ReadOnlyMemory<T> around it if you want.

I'm using the terms "own" and "ownership" because these are the wordings used in the official usage guidelines. But my understanding is that "owning" a Memory/ROM simply means that you are responsible for its lifetime management, i.e. disposing of the underlying storage at an appropriate time. It does not necessarily mean that you should have or need unrestricted access. I personally think that wording like "responsibility to dispose" would be more accurate than "ownership". Please feel free to disagree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Memory untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

3 participants