Skip to content
This repository was archived by the owner on Mar 14, 2026. It is now read-only.
Draft
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This is a fork of [DotNetty](https://github.com/azure/dotnetty).
| .NET Netstandard (Windows) Unit Tests | [![Build status](https://ci.appveyor.com/api/projects/status/rvx3h1bmahad2giw/branch/main?svg=true)](https://ci.appveyor.com/project/cuteant/SpanNetty/branch/main) |

## Features
- Align with [Netty-4.1.51.Final](https://github.com/netty/netty/tree/netty-4.1.51.Final)
- Align with [Netty-4.1.52.Final](https://github.com/netty/netty/tree/netty-4.1.52.Final)
- ArrayPooledByteBuffer
- Support **Span<byte>** and **Memory<byte>** in Buffer/Common APIs
- Add support for IBufferWriter<byte> to the **IByteBuffer**
Expand Down
12 changes: 8 additions & 4 deletions src/DotNetty.Buffers/AbstractArrayPooledDerivedByteBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,16 @@ protected IByteBuffer Duplicate0()

sealed class ArrayPooledNonRetainedDuplicateByteBuffer : UnpooledDuplicatedByteBuffer
{
readonly IReferenceCounted _referenceCountDelegate;
readonly IByteBuffer _referenceCountDelegate;

internal ArrayPooledNonRetainedDuplicateByteBuffer(IReferenceCounted referenceCountDelegate, AbstractByteBuffer buffer)
internal ArrayPooledNonRetainedDuplicateByteBuffer(IByteBuffer referenceCountDelegate, AbstractByteBuffer buffer)
: base(buffer)
{
_referenceCountDelegate = referenceCountDelegate;
}

protected override bool IsAccessible0() => _referenceCountDelegate.IsAccessible;

protected override int ReferenceCount0() => _referenceCountDelegate.ReferenceCount;

protected override IByteBuffer Retain0()
Expand Down Expand Up @@ -192,14 +194,16 @@ public override IByteBuffer Slice(int index, int length)

sealed class ArrayPooledNonRetainedSlicedByteBuffer : UnpooledSlicedByteBuffer
{
readonly IReferenceCounted _referenceCountDelegate;
readonly IByteBuffer _referenceCountDelegate;

public ArrayPooledNonRetainedSlicedByteBuffer(IReferenceCounted referenceCountDelegate, AbstractByteBuffer buffer, int index, int length)
public ArrayPooledNonRetainedSlicedByteBuffer(IByteBuffer referenceCountDelegate, AbstractByteBuffer buffer, int index, int length)
: base(buffer, index, length)
{
_referenceCountDelegate = referenceCountDelegate;
}

protected override bool IsAccessible0() => _referenceCountDelegate.IsAccessible;

protected override int ReferenceCount0() => _referenceCountDelegate.ReferenceCount;

protected override IByteBuffer Retain0()
Expand Down
4 changes: 3 additions & 1 deletion src/DotNetty.Buffers/AbstractDerivedByteBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ protected AbstractDerivedByteBuffer(int maxCapacity)
{
}

public sealed override bool IsAccessible => Unwrap().IsAccessible;
public sealed override bool IsAccessible => IsAccessible0();

protected virtual bool IsAccessible0() => Unwrap().IsAccessible;

public sealed override int ReferenceCount => ReferenceCount0();

Expand Down
12 changes: 8 additions & 4 deletions src/DotNetty.Buffers/AbstractPooledDerivedByteBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,16 @@ protected IByteBuffer Duplicate0()

sealed class PooledNonRetainedDuplicateByteBuffer : UnpooledDuplicatedByteBuffer
{
readonly IReferenceCounted _referenceCountDelegate;
readonly IByteBuffer _referenceCountDelegate;

internal PooledNonRetainedDuplicateByteBuffer(IReferenceCounted referenceCountDelegate, AbstractByteBuffer buffer)
internal PooledNonRetainedDuplicateByteBuffer(IByteBuffer referenceCountDelegate, AbstractByteBuffer buffer)
: base(buffer)
{
_referenceCountDelegate = referenceCountDelegate;
}

protected override bool IsAccessible0() => _referenceCountDelegate.IsAccessible;

protected override int ReferenceCount0() => _referenceCountDelegate.ReferenceCount;

protected override IByteBuffer Retain0()
Expand Down Expand Up @@ -198,14 +200,16 @@ public override IByteBuffer Slice(int index, int length)

sealed class PooledNonRetainedSlicedByteBuffer : UnpooledSlicedByteBuffer
{
readonly IReferenceCounted _referenceCountDelegate;
readonly IByteBuffer _referenceCountDelegate;

public PooledNonRetainedSlicedByteBuffer(IReferenceCounted referenceCountDelegate, AbstractByteBuffer buffer, int index, int length)
public PooledNonRetainedSlicedByteBuffer(IByteBuffer referenceCountDelegate, AbstractByteBuffer buffer, int index, int length)
: base(buffer, index, length)
{
_referenceCountDelegate = referenceCountDelegate;
}

protected override bool IsAccessible0() => _referenceCountDelegate.IsAccessible;

protected override int ReferenceCount0() => _referenceCountDelegate.ReferenceCount;

protected override IByteBuffer Retain0()
Expand Down
34 changes: 28 additions & 6 deletions src/DotNetty.Buffers/ByteBufferUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,33 @@ static ByteBufferUtil()
AsciiByteProcessor = new FindNonAscii();
}

[MethodImpl(InlineMethod.AggressiveOptimization)]
public static bool EnsureWritableSuccess(int ensureWritableResult)
{
var nresult = (uint)ensureWritableResult;
return 0u >= nresult || 2u == nresult;
}

/// <summary>whether the specified buffer has a nonzero ref count.</summary>
[MethodImpl(InlineMethod.AggressiveOptimization)]
public static bool IsAccessible(IByteBuffer buffer)
{
//if (buffer is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.buffer); }
return buffer.IsAccessible;
}

/// <summary>throws IllegalReferenceCountException if the buffer has a zero ref count.</summary>
[MethodImpl(InlineMethod.AggressiveOptimization)]
public static IByteBuffer EnsureAccessible(IByteBuffer buffer)
{
//if (buffer is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.buffer); }
if (!buffer.IsAccessible)
{
ThrowHelper.ThrowIllegalReferenceCountException(buffer.ReferenceCount);
}
return buffer;
}

/// <summary>
/// Read the given amount of bytes into a new <see cref="IByteBuffer"/> that is allocated from the <see cref="IByteBufferAllocator"/>.
/// </summary>
Expand Down Expand Up @@ -148,16 +169,17 @@ public static byte[] GetBytes(IByteBuffer buf, int start, int length, bool copy)

if (buf.HasArray)
{
if (copy || start != 0 || length != capacity)
int baseOffset = buf.ArrayOffset + start;
var bytes = buf.Array;
if (copy || baseOffset != 0 || length != bytes.Length)
{
int baseOffset = buf.ArrayOffset + start;
var bytes = new byte[length];
PlatformDependent.CopyMemory(buf.Array, baseOffset, bytes, 0, length);
return bytes;
var result = new byte[length];
PlatformDependent.CopyMemory(bytes, baseOffset, result, 0, length);
return result;
}
else
{
return buf.Array;
return bytes;
}
}

Expand Down
14 changes: 1 addition & 13 deletions src/DotNetty.Buffers/DefaultByteBufferHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,7 @@ public DefaultByteBufferHolder(IByteBuffer data)
_data = data;
}

public IByteBuffer Content
{
get
{
var refCnt = _data.ReferenceCount;
if ((uint)(refCnt - 1) > SharedConstants.TooBigOrNegative) // <= 0
{
ThrowHelper.ThrowIllegalReferenceCountException(refCnt);
}

return _data;
}
}
public IByteBuffer Content => ByteBufferUtil.EnsureAccessible(_data);

public virtual IByteBufferHolder Copy() => Replace(_data.Copy());

Expand Down
55 changes: 31 additions & 24 deletions src/DotNetty.Buffers/IPoolArenaMetric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,77 +25,84 @@

namespace DotNetty.Buffers
{
using System;
using System.Collections.Generic;

public interface IPoolArenaMetric
/// <summary>Expose metrics for an arena.</summary>
public interface IPoolArenaMetric : ISizeClassesMetric
{
/// Returns the number of thread caches backed by this arena.
/// <summary>Returns the number of thread caches backed by this arena.</summary>
int NumThreadCaches { get; }

/// Returns the number of tiny sub-pages for the arena.
/// <summary>Returns the number of tiny sub-pages for the arena.</summary>
[Obsolete("Tiny sub-pages have been merged into small sub-pages.")]
int NumTinySubpages { get; }

/// Returns the number of small sub-pages for the arena.
/// <summary>Returns the number of small sub-pages for the arena.</summary>
int NumSmallSubpages { get; }

/// Returns the number of chunk lists for the arena.
/// <summary>Returns the number of chunk lists for the arena.</summary>
int NumChunkLists { get; }

/// Returns an unmodifiable {@link List} which holds {@link PoolSubpageMetric}s for tiny sub-pages.
/// <summary>Returns an unmodifiable <see cref="IReadOnlyList{T}"/> which holds <see cref="IPoolSubpageMetric"/>s for tiny sub-pages.</summary>
[Obsolete("Tiny sub-pages have been merged into small sub-pages.")]
IReadOnlyList<IPoolSubpageMetric> TinySubpages { get; }

/// Returns an unmodifiable {@link List} which holds {@link PoolSubpageMetric}s for small sub-pages.
/// <summary>Returns an unmodifiable <see cref="IReadOnlyList{T}"/> which holds <see cref="IPoolSubpageMetric"/>s for small sub-pages.</summary>
IReadOnlyList<IPoolSubpageMetric> SmallSubpages { get; }

/// Returns an unmodifiable {@link List} which holds {@link PoolChunkListMetric}s.
/// <summary>Returns an unmodifiable <see cref="IReadOnlyList{T}"/> which holds <see cref="IPoolChunkListMetric"/>s.</summary>
IReadOnlyList<IPoolChunkListMetric> ChunkLists { get; }

/// Return the number of allocations done via the arena. This includes all sizes.
/// <summary>Return the number of allocations done via the arena. This includes all sizes.</summary>
long NumAllocations { get; }

/// Return the number of tiny allocations done via the arena.
/// <summary>Return the number of tiny allocations done via the arena.</summary>
[Obsolete("Tiny allocations have been merged into small allocations.")]
long NumTinyAllocations { get; }

/// Return the number of small allocations done via the arena.
/// <summary>Return the number of small allocations done via the arena.</summary>
long NumSmallAllocations { get; }

/// Return the number of normal allocations done via the arena.
/// <summary>Return the number of normal allocations done via the arena.</summary>
long NumNormalAllocations { get; }

/// Return the number of huge allocations done via the arena.
/// <summary>Return the number of huge allocations done via the arena.</summary>
long NumHugeAllocations { get; }

/// Return the number of deallocations done via the arena. This includes all sizes.
/// <summary>Return the number of deallocations done via the arena. This includes all sizes.</summary>
long NumDeallocations { get; }

/// Return the number of tiny deallocations done via the arena.
/// <summary>Return the number of tiny deallocations done via the arena.</summary>
[Obsolete("Tiny deallocations have been merged into small deallocations.")]
long NumTinyDeallocations { get; }

/// Return the number of small deallocations done via the arena.
/// <summary>Return the number of small deallocations done via the arena.</summary>
long NumSmallDeallocations { get; }

/// Return the number of normal deallocations done via the arena.
/// <summary>Return the number of normal deallocations done via the arena.</summary>
long NumNormalDeallocations { get; }

/// Return the number of huge deallocations done via the arena.
/// <summary>Return the number of huge deallocations done via the arena.</summary>
long NumHugeDeallocations { get; }

/// Return the number of currently active allocations.
/// <summary>Return the number of currently active allocations.</summary>
long NumActiveAllocations { get; }

/// Return the number of currently active tiny allocations.
/// <summary>Return the number of currently active tiny allocations.</summary>
[Obsolete("Tiny allocations have been merged into small allocations.")]
long NumActiveTinyAllocations { get; }

/// Return the number of currently active small allocations.
/// <summary>Return the number of currently active small allocations.</summary>
long NumActiveSmallAllocations { get; }

/// Return the number of currently active normal allocations.
/// <summary>Return the number of currently active normal allocations.</summary>
long NumActiveNormalAllocations { get; }

/// Return the number of currently active huge allocations.
/// <summary>Return the number of currently active huge allocations.</summary>
long NumActiveHugeAllocations { get; }

/// Return the number of active bytes that are currently allocated by the arena.
/// <summary>Return the number of active bytes that are currently allocated by the arena.</summary>
long NumActiveBytes { get; }
}
}
4 changes: 2 additions & 2 deletions src/DotNetty.Buffers/IPoolChunkListMetric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ namespace DotNetty.Buffers

public interface IPoolChunkListMetric : IEnumerable<IPoolChunkMetric>
{
/// Return the minum usage of the chunk list before which chunks are promoted to the previous list.
/// <summary>Return the minum usage of the chunk list before which chunks are promoted to the previous list.</summary>
int MinUsage { get; }

/// Return the minum usage of the chunk list after which chunks are promoted to the next list.
/// <summary>Return the minum usage of the chunk list after which chunks are promoted to the next list.</summary>
int MaxUsage { get; }
}
}
6 changes: 3 additions & 3 deletions src/DotNetty.Buffers/IPoolChunkMetric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ namespace DotNetty.Buffers
{
public interface IPoolChunkMetric
{
/// Return the percentage of the current usage of the chunk.
/// <summary>Return the percentage of the current usage of the chunk.</summary>
int Usage { get; }

/// Return the size of the chunk in bytes, this is the maximum of bytes that can be served out of the chunk.
/// <summary>Return the size of the chunk in bytes, this is the maximum of bytes that can be served out of the chunk.</summary>
int ChunkSize { get; }

/// Return the number of free bytes in the chunk.
/// <summary>Return the number of free bytes in the chunk.</summary>
int FreeBytes { get; }
}
}
8 changes: 4 additions & 4 deletions src/DotNetty.Buffers/IPoolSubpageMetric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ namespace DotNetty.Buffers
{
public interface IPoolSubpageMetric
{
/// Return the number of maximal elements that can be allocated out of the sub-page.
/// <summary>Return the number of maximal elements that can be allocated out of the sub-page.</summary>
int MaxNumElements { get; }

/// Return the number of available elements to be allocated.
/// <summary>Return the number of available elements to be allocated.</summary>
int NumAvailable { get; }

/// Return the size (in bytes) of the elements that will be allocated.
/// <summary>Return the size (in bytes) of the elements that will be allocated.</summary>
int ElementSize { get; }

/// Return the size (in bytes) of this page.
/// <summary>Return the page size (in bytes) of this page.</summary>
int PageSize { get; }
}
}
Loading