Prepare for zero-copy sending
This commit is contained in:
@@ -27,7 +27,7 @@ class Program
|
|||||||
var listening = new IPEndPoint(IPAddress.Any, 4567);
|
var listening = new IPEndPoint(IPAddress.Any, 4567);
|
||||||
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = listening);
|
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = listening);
|
||||||
builder.Services.AddSingleton<IDistributionModule, ExtractorFirstDistributionModule>();
|
builder.Services.AddSingleton<IDistributionModule, ExtractorFirstDistributionModule>();
|
||||||
|
builder.Services.Configure<SerializationBufferOffset>(options => options.Offset = 0);
|
||||||
builder.Services.AddSingleton<HubRequestExtractor>();
|
builder.Services.AddSingleton<HubRequestExtractor>();
|
||||||
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
|
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
|
||||||
builder.Services.AddSingleton<IRepresentationModuleProducer, CreativeRepresentationModuleProducer>();
|
builder.Services.AddSingleton<IRepresentationModuleProducer, CreativeRepresentationModuleProducer>();
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class Program
|
|||||||
builder.Services.AddOptions();
|
builder.Services.AddOptions();
|
||||||
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint);
|
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint);
|
||||||
builder.Services.Configure<DistributionOptions>(o => o.DistributionType = EDistributionType.Channeled);
|
builder.Services.Configure<DistributionOptions>(o => o.DistributionType = EDistributionType.Channeled);
|
||||||
|
builder.Services.Configure<SerializationBufferOffset>(options => options.Offset = 0);
|
||||||
|
|
||||||
builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>();
|
builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>();
|
||||||
builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>();
|
builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
|||||||
using System.Formats.Cbor;
|
using System.Formats.Cbor;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
@@ -15,7 +16,12 @@ namespace mROA.Cbor
|
|||||||
public class CborSerializationToolkit : IContextualSerializationToolKit
|
public class CborSerializationToolkit : IContextualSerializationToolKit
|
||||||
{
|
{
|
||||||
private readonly CborWriter _writer = new(initialCapacity: 2048);
|
private readonly CborWriter _writer = new(initialCapacity: 2048);
|
||||||
|
private readonly int _offset;
|
||||||
|
|
||||||
|
public CborSerializationToolkit(IOptions<SerializationBufferOffset> offsetOptions) : this(offsetOptions.Value.Offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private readonly IOrdinaryStructureParser[] _parsers =
|
private readonly IOrdinaryStructureParser[] _parsers =
|
||||||
{
|
{
|
||||||
new CallRequestParser(), new FinalCommandExecutionParser(),
|
new CallRequestParser(), new FinalCommandExecutionParser(),
|
||||||
@@ -23,6 +29,12 @@ namespace mROA.Cbor
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly Dictionary<Type, List<PropertyInfo>> _propertiesCache = new();
|
private readonly Dictionary<Type, List<PropertyInfo>> _propertiesCache = new();
|
||||||
|
|
||||||
|
public CborSerializationToolkit(int offset)
|
||||||
|
{
|
||||||
|
_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
public static TimeSpan SerializationTime = TimeSpan.Zero;
|
public static TimeSpan SerializationTime = TimeSpan.Zero;
|
||||||
|
|
||||||
private bool FindParser(Type t, out IOrdinaryStructureParser parser)
|
private bool FindParser(Type t, out IOrdinaryStructureParser parser)
|
||||||
@@ -56,7 +68,9 @@ namespace mROA.Cbor
|
|||||||
{
|
{
|
||||||
_writer.Reset();
|
_writer.Reset();
|
||||||
WriteData(objectToSerialize, _writer, context);
|
WriteData(objectToSerialize, _writer, context);
|
||||||
result = _writer.Encode();
|
result = new byte[_offset + _writer.BytesWritten];
|
||||||
|
var span = result.AsSpan();
|
||||||
|
_writer.Encode(span[_offset..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -94,18 +108,13 @@ namespace mROA.Cbor
|
|||||||
var reader = new CborReader(rawMemory);
|
var reader = new CborReader(rawMemory);
|
||||||
return ReadData(reader, type, context);
|
return ReadData(reader, type, context);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Bad deserialization. Bytes: {rawMemory.ToArray().Select(b => $"{b:X}")}");
|
Console.WriteLine($"Bad deserialization. Bytes: {BitConverter.ToString(rawMemory.ToArray())}");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Cast<T>(object nonCasted, IEndPointContext? context)
|
|
||||||
{
|
|
||||||
return (T)Cast(nonCasted, typeof(T), context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object? Cast(object? nonCasted, Type type, IEndPointContext? context)
|
public object? Cast(object? nonCasted, Type type, IEndPointContext? context)
|
||||||
{
|
{
|
||||||
if (nonCasted == null)
|
if (nonCasted == null)
|
||||||
@@ -133,7 +142,7 @@ namespace mROA.Cbor
|
|||||||
|
|
||||||
public IContextualSerializationToolKit Clone()
|
public IContextualSerializationToolKit Clone()
|
||||||
{
|
{
|
||||||
return new CborSerializationToolkit();
|
return new CborSerializationToolkit(_offset) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteData(object? obj, CborWriter writer, IEndPointContext? context)
|
public void WriteData(object? obj, CborWriter writer, IEndPointContext? context)
|
||||||
@@ -465,7 +474,7 @@ namespace mROA.Cbor
|
|||||||
value = Convert.ChangeType(value, typeof(byte));
|
value = Convert.ChangeType(value, typeof(byte));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property.SetValue(obj, value);
|
property.SetValue(obj, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace mROA.Codegen
|
|||||||
ReturnType = typeof(<!L returnType>),
|
ReturnType = typeof(<!L returnType>),
|
||||||
ParameterTypes = new Type[] { <!L parametersType> },
|
ParameterTypes = new Type[] { <!L parametersType> },
|
||||||
SuitableType = typeof(<!L suitableType>),
|
SuitableType = typeof(<!L suitableType>),
|
||||||
|
RequireCancellation = <!L cancellation>,
|
||||||
Invoking = (i, parameters, special, post) => <!L funcInvoking>,
|
Invoking = (i, parameters, special, post) => <!L funcInvoking>,
|
||||||
}<!T>
|
}<!T>
|
||||||
<!T syncInvoker>
|
<!T syncInvoker>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string ParametersTypeTag = "parametersType";
|
private const string ParametersTypeTag = "parametersType";
|
||||||
private const string SuitableTypeTag = "suitableType";
|
private const string SuitableTypeTag = "suitableType";
|
||||||
private const string FuncInvokingTag = "funcInvoking";
|
private const string FuncInvokingTag = "funcInvoking";
|
||||||
|
private const string CancellationTag = "cancellation";
|
||||||
private const string IsTrustedTag = "isTrusted";
|
private const string IsTrustedTag = "isTrusted";
|
||||||
|
|
||||||
public InvokerTemplate(TemplateDocument template) : base(template) { }
|
public InvokerTemplate(TemplateDocument template) : base(template) { }
|
||||||
@@ -42,5 +43,10 @@ namespace mROA.Codegen.Templates
|
|||||||
{
|
{
|
||||||
Define(IsTrustedTag, value);
|
Define(IsTrustedTag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DefineCancellation(string value)
|
||||||
|
{
|
||||||
|
Define(CancellationTag, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,11 +316,14 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
var parametersInsertList = new List<string>();
|
var parametersInsertList = new List<string>();
|
||||||
|
|
||||||
|
var useCancellationToken = false;
|
||||||
|
|
||||||
foreach (var parameter in method.Parameters)
|
foreach (var parameter in method.Parameters)
|
||||||
switch (parameter.Type.Name)
|
switch (parameter.Type.Name)
|
||||||
{
|
{
|
||||||
case "CancellationToken":
|
case "CancellationToken":
|
||||||
parametersInsertList.Add("(CancellationToken)special[1]");
|
parametersInsertList.Add("(CancellationToken)special[1]");
|
||||||
|
useCancellationToken = true;
|
||||||
break;
|
break;
|
||||||
case "RequestContext":
|
case "RequestContext":
|
||||||
parametersInsertList.Add("(RequestContext)special[0]");
|
parametersInsertList.Add("(RequestContext)special[0]");
|
||||||
@@ -359,6 +362,7 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
||||||
|
invokerTemplate.DefineCancellation(useCancellationToken.ToString().ToLower());
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -370,6 +374,7 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,20 +145,29 @@ namespace mROA.Implementation.Backend
|
|||||||
CallRequest command, ICancellationRepository cancellationRepository,
|
CallRequest command, ICancellationRepository cancellationRepository,
|
||||||
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
CancellationToken? token = null;
|
||||||
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
if (invoker.RequireCancellation)
|
||||||
var token = tokenSource.Token;
|
{
|
||||||
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||||
|
|
||||||
|
token = tokenSource.Token;
|
||||||
|
}
|
||||||
|
|
||||||
invoker.Invoke(instance, parameters, new object[] { executionContext, token }, _ =>
|
invoker.Invoke(instance, parameters, new object[] { executionContext, token }, _ =>
|
||||||
{
|
{
|
||||||
if (token.IsCancellationRequested)
|
if (invoker.RequireCancellation)
|
||||||
return;
|
{
|
||||||
|
_cancellationRepo.FreeCancellation(command.Id);
|
||||||
|
|
||||||
|
if (token.Value.IsCancellationRequested)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var payload = new FinalCommandExecution
|
var payload = new FinalCommandExecution
|
||||||
{
|
{
|
||||||
Id = command.Id
|
Id = command.Id
|
||||||
};
|
};
|
||||||
_cancellationRepo.FreeCancellation(command.Id);
|
|
||||||
|
|
||||||
|
|
||||||
if (invoker.IsTrusted)
|
if (invoker.IsTrusted)
|
||||||
@@ -174,20 +183,31 @@ namespace mROA.Implementation.Backend
|
|||||||
CallRequest command, ICancellationRepository cancellationRepository,
|
CallRequest command, ICancellationRepository cancellationRepository,
|
||||||
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
CancellationToken? token = null;
|
||||||
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
if (invoker.RequireCancellation)
|
||||||
|
{
|
||||||
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||||
|
|
||||||
var token = tokenSource.Token;
|
token = tokenSource.Token;
|
||||||
|
}
|
||||||
|
|
||||||
invoker.Invoke(instance, parameters, new object[] { executionContext, token },
|
invoker.Invoke(instance, parameters, new object[] { executionContext, token },
|
||||||
finalResult =>
|
finalResult =>
|
||||||
{
|
{
|
||||||
|
if (invoker.RequireCancellation)
|
||||||
|
{
|
||||||
|
_cancellationRepo.FreeCancellation(command.Id);
|
||||||
|
|
||||||
|
if (token.Value.IsCancellationRequested)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var payload = new FinalCommandExecution<object>
|
var payload = new FinalCommandExecution<object>
|
||||||
{
|
{
|
||||||
Id = command.Id,
|
Id = command.Id,
|
||||||
Result = finalResult
|
Result = finalResult
|
||||||
};
|
};
|
||||||
_cancellationRepo.FreeCancellation(command.Id);
|
|
||||||
|
|
||||||
representationModule.PostCallMessageAsync(command.Id, EMessageType.FinishedCommandExecution,
|
representationModule.PostCallMessageAsync(command.Id, EMessageType.FinishedCommandExecution,
|
||||||
payload, context);
|
payload, context);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
@@ -5,16 +6,16 @@ namespace mROA.Implementation
|
|||||||
{
|
{
|
||||||
public class CollectableMethodRepository : IMethodRepository
|
public class CollectableMethodRepository : IMethodRepository
|
||||||
{
|
{
|
||||||
private readonly List<IMethodInvoker> _methods = new();
|
private readonly List<IMethodInvoker> _methods = new() { MethodInvoker.Dispose };
|
||||||
|
private IMethodInvoker[] _baked = Array.Empty<IMethodInvoker>();
|
||||||
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
|
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
|
||||||
{
|
{
|
||||||
_methods.AddRange(methodInvokers);
|
_methods.AddRange(methodInvokers);
|
||||||
|
_baked = _methods.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethodInvoker GetMethod(int id)
|
public IMethodInvoker GetMethod(int id)
|
||||||
{
|
{
|
||||||
return id == -1 ? MethodInvoker.Dispose : _methods[id];
|
return _baked[++id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ namespace mROA.Implementation
|
|||||||
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
|
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
|
||||||
public Type? ReturnType { get; set; }
|
public Type? ReturnType { get; set; }
|
||||||
public Type SuitableType { get; set; } = typeof(object);
|
public Type SuitableType { get; set; } = typeof(object);
|
||||||
|
public bool RequireCancellation { get; set; } = true;
|
||||||
public Action<object, object?[]?, object[], Action<object?>> Invoking { get; set; } =
|
public Action<object, object?[]?, object[], Action<object?>> Invoking { get; set; } =
|
||||||
(_, _, _, post) => { post.Invoke(null); };
|
(_, _, _, post) => { post.Invoke(null); };
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace mROA.Implementation
|
||||||
|
{
|
||||||
|
public class SerializationBufferOffset
|
||||||
|
{
|
||||||
|
public int Offset { get; set; } = 19;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user