Skip to content

Commit

Permalink
feat: adding way to call SendNotify without allocations and example (#…
Browse files Browse the repository at this point in the history
…875)

* feat: adding way to call SendNotify without allocations

* adding some code to show how to use INotifyCallBack

* adding new methods to pipe

* removing duplicate code

* removing todo

* fixing code smells

* pipe tests

* adding test for callbacks
  • Loading branch information
James-Frowen committed Aug 6, 2021
1 parent 23f5e7c commit 16b3000
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 17 deletions.
10 changes: 10 additions & 0 deletions Assets/Mirage/Runtime/PipePeerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,17 @@ public INotifyToken SendNotify(byte[] packet, int offset, int length)
public INotifyToken SendNotify(ArraySegment<byte> packet) => SendNotify(packet.Array, packet.Offset, packet.Count);
public INotifyToken SendNotify(byte[] packet) => SendNotify(packet, 0, packet.Length);

public void SendNotify(byte[] packet, int offset, int length, INotifyCallBack callBacks)
{
if (State == ConnectionState.Disconnected)
return;

receive(packet, offset, length);

callBacks.OnDelivered();
}
public void SendNotify(ArraySegment<byte> packet, INotifyCallBack callBacks) => SendNotify(packet.Array, packet.Offset, packet.Count, callBacks);
public void SendNotify(byte[] packet, INotifyCallBack callBacks) => SendNotify(packet, 0, packet.Length, callBacks);


public void SendReliable(byte[] message, int offset, int length)
Expand Down
25 changes: 16 additions & 9 deletions Assets/Mirage/Runtime/SocketLayer/AckSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,21 +237,28 @@ private void SendAck()
}
}

/// <summary>
/// Use <see cref="SendNotify(byte[], int, int, INotifyCallBack)"/> for non-alloc version
/// </summary>
public INotifyToken SendNotify(byte[] inPacket, int inOffset, int inLength)
{
// todo batch Notify?
var token = new NotifyToken();
SendNotify(inPacket, inOffset, inLength, token);
return token;
}

public void SendNotify(byte[] inPacket, int inOffset, int inLength, INotifyCallBack callBacks)
{
if (inLength + NOTIFY_HEADER_SIZE > maxPacketSize)
{
throw new IndexOutOfRangeException($"Message is bigger than MTU, max Notify message size is {maxPacketSize - NOTIFY_HEADER_SIZE}");
throw new ArgumentException($"Message is bigger than MTU, max Notify message size is {maxPacketSize - NOTIFY_HEADER_SIZE}");
}
if (sentAckablePackets.IsFull)
{
throw new InvalidOperationException("Sent queue is full");
}

// todo use pool to stop allocations
var token = new NotifyToken();
ushort sequence = (ushort)sentAckablePackets.Enqueue(new AckablePacket(token));
ushort sequence = (ushort)sentAckablePackets.Enqueue(new AckablePacket(callBacks));

using (ByteBuffer buffer = bufferPool.Take())
{
Expand All @@ -268,10 +275,10 @@ public INotifyToken SendNotify(byte[] inPacket, int inOffset, int inLength)

Send(outPacket, outOffset + inLength);
}

return token;
}



public void SendReliable(byte[] message, int offset, int length)
{
if (sentAckablePackets.IsFull)
Expand Down Expand Up @@ -652,13 +659,13 @@ static bool NotInMask(int distance, ulong receivedMask)

struct AckablePacket : IEquatable<AckablePacket>
{
public NotifyToken token;
public INotifyCallBack token;
public ReliablePacket reliablePacket;

public bool IsNotify => token != null;
public bool IsReliable => reliablePacket != null;

public AckablePacket(NotifyToken token)
public AckablePacket(INotifyCallBack token)
{
this.token = token;
reliablePacket = null;
Expand Down
36 changes: 35 additions & 1 deletion Assets/Mirage/Runtime/SocketLayer/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ public interface IConnection
INotifyToken SendNotify(byte[] packet, int offset, int length);
INotifyToken SendNotify(ArraySegment<byte> packet);

void SendNotify(byte[] packet, INotifyCallBack callBacks);
void SendNotify(byte[] packet, int offset, int length, INotifyCallBack callBacks);
void SendNotify(ArraySegment<byte> packet, INotifyCallBack callBacks);

/// <summary>
/// single message, batched by AckSystem
/// </summary>
Expand Down Expand Up @@ -175,20 +179,50 @@ public void SendUnreliable(ArraySegment<byte> packet)
SendUnreliable(packet.Array, packet.Offset, packet.Count);
}


/// <summary>
/// Use <see cref="INotifyCallBack"/> version for non-alloc
/// </summary>
public INotifyToken SendNotify(byte[] packet, int offset, int length)
{
ThrowIfNotConnected();
return ackSystem.SendNotify(packet, offset, length);
}
/// <summary>
/// Use <see cref="INotifyCallBack"/> version for non-alloc
/// </summary>
public INotifyToken SendNotify(byte[] packet)
{
return SendNotify(packet, 0, packet.Length);
}
/// <summary>
/// Use <see cref="INotifyCallBack"/> version for non-alloc
/// </summary>
public INotifyToken SendNotify(ArraySegment<byte> packet)
{
return SendNotify(packet.Array, packet.Offset, packet.Count);
}

/// <summary>
/// Use <see cref="INotifyCallBack"/> version for non-alloc
/// </summary>
public void SendNotify(byte[] packet, int offset, int length, INotifyCallBack callBacks)
{
ThrowIfNotConnected();
ackSystem.SendNotify(packet, offset, length, callBacks);
}
/// <summary>
/// Use <see cref="INotifyCallBack"/> version for non-alloc
/// </summary>
public void SendNotify(byte[] packet, INotifyCallBack callBacks)
{
SendNotify(packet, 0, packet.Length, callBacks);
}
/// <summary>
/// Use <see cref="INotifyCallBack"/> version for non-alloc
/// </summary>
public void SendNotify(ArraySegment<byte> packet, INotifyCallBack callBacks)
{
SendNotify(packet.Array, packet.Offset, packet.Count, callBacks);
}


Expand Down
42 changes: 35 additions & 7 deletions Assets/Mirage/Runtime/SocketLayer/NotifyToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
namespace Mirage.SocketLayer
{
/// <summary>
/// <summary>
/// Object returned from <see cref="NotifySystem.Send(byte[])"/> with events for when packet is Lost or Delivered
/// Object returned from <see cref="AckSystem.SendNotify"/> with events for when packet is Lost or Delivered
/// </summary>
public interface INotifyToken
{
Expand All @@ -14,24 +13,53 @@ public interface INotifyToken


/// <summary>
/// Object returned from <see cref="NotifySystem.Send(byte[])"/> with events for when packet is Lost or Delivered
/// Object returned from <see cref="AckSystem.SendNotify"/> with events for when packet is Lost or Delivered
/// </summary>
public class NotifyToken : INotifyToken
public class NotifyToken : INotifyToken, INotifyCallBack
{
public event Action Delivered;
public event Action Lost;

bool notified;

internal void Notify(bool delivered)

public void OnDelivered()
{
if (notified) throw new InvalidOperationException("this token as already been notified");
notified = true;

Delivered?.Invoke();
}

public void OnLost()
{
if (notified) throw new InvalidOperationException("this token as already been notified");
notified = true;

Lost?.Invoke();
}
}

public static class INotifyCallBackExtensions
{
public static void Notify(this INotifyCallBack callBack, bool delivered)
{
if (delivered)
Delivered?.Invoke();
callBack.OnDelivered();
else
Lost?.Invoke();
callBack.OnLost();
}
}

/// <summary>
/// Can be passed into <see cref="AckSystem.SendNotify(byte[], int, int, INotifyCallBack)"/> and methods will be invoked when notify is delivered or lost
/// <para>
/// See the Notify Example on how to use this interface
/// </para>
/// </summary>
public interface INotifyCallBack
{
void OnDelivered();
void OnLost();
}
}
8 changes: 8 additions & 0 deletions Assets/Mirage/Samples~/Notify.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions Assets/Mirage/Samples~/Notify/Mirage.Examples.Notify.asmdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Mirage.Examples.Notify",
"references": [
"GUID:30817c1a0e6d646d99c048fc403f5979",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:96f081f4a0d214ee39e3aa34e9d43109",
"GUID:c0b2064c294eb174c9f3f7da398eb677"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 16b3000

Please sign in to comment.