diff --git a/Example.Backend/Printer.cs b/Example.Backend/Printer.cs index 65125f4..2bfc5a1 100644 --- a/Example.Backend/Printer.cs +++ b/Example.Backend/Printer.cs @@ -10,7 +10,7 @@ namespace Example.Backend { public string Name; - public void OnPrintExternal(IPage p0) + public void OnPrintExternal(IPage p0, RequestContext ro) { } @@ -27,12 +27,12 @@ namespace Example.Backend // throw new Exception("The method or operation is not implemented."); var page = new Page { Text = text }; Console.WriteLine($"Request id : :{context.RequestId}"); - OnPrint?.Invoke(page); + OnPrint?.Invoke(page, new RequestContext(context.RequestId, -1000)); Resource /= 1.5; return page; } - public event Action? OnPrint; + public event Action? OnPrint; public void Dispose() { diff --git a/Example.Frontend/ClientBasedPrinter.cs b/Example.Frontend/ClientBasedPrinter.cs index e749687..0686390 100644 --- a/Example.Frontend/ClientBasedPrinter.cs +++ b/Example.Frontend/ClientBasedPrinter.cs @@ -8,7 +8,7 @@ namespace Example.Frontend { public class ClientBasedPrinter : IPrinter { - public void OnPrintExternal(IPage p0) + public void OnPrintExternal(IPage p0, RequestContext ro) { } @@ -29,7 +29,7 @@ namespace Example.Frontend return new ClientBasedPage(); } - public event Action? OnPrint; + public event Action? OnPrint; public void Dispose() { diff --git a/Example.Frontend/Program.cs b/Example.Frontend/Program.cs index 077c228..c47bec3 100644 --- a/Example.Frontend/Program.cs +++ b/Example.Frontend/Program.cs @@ -43,12 +43,12 @@ class Program Console.WriteLine(TransmissionConfig.OwnershipRepository.GetOwnershipId()); var context = builder.GetModule(); - var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory; + var factory = context.GetSingleObject(typeof(IPrinterFactory), 0) as IPrinterFactory; //правильный порядок команд 8-5-10-7 using (var disposingPrinter = factory.Create("Test")) { - disposingPrinter.OnPrint += page1 => { Console.WriteLine("New page creater. Called from event!!!"); }; + disposingPrinter.OnPrint += (_, _) => { Console.WriteLine("New page creater. Called from event!!!"); }; Console.WriteLine("Printer created"); Thread.Sleep(100); @@ -90,7 +90,7 @@ class Program } - var loadSingleton = context.GetSingleObject(typeof(ILoadTest)) as ILoadTest; + var loadSingleton = context.GetSingleObject(typeof(ILoadTest), 0) as ILoadTest; var cts = new CancellationTokenSource(); diff --git a/Example.Shared/IPrinter.cs b/Example.Shared/IPrinter.cs index 3b320fd..f5b25f0 100644 --- a/Example.Shared/IPrinter.cs +++ b/Example.Shared/IPrinter.cs @@ -12,6 +12,6 @@ namespace Example.Shared double Resource { get; set; } string GetName(); Task Print(string text, bool someParameter, RequestContext context, CancellationToken cancellationToken); - event Action OnPrint; + event Action OnPrint; } } \ No newline at end of file diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index ed5abd2..651dd1b 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -481,7 +481,7 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()} {callFilter} var request = new DefaultCallRequest {{ - CommandId = {index}, ObjectId = new ComplexObjectIdentifier(index, context.OwnerId), Parameters = new object[] {{ {transferParameters} }} + CommandId = {index}, ObjectId = new ComplexObjectIdentifier(index, context.HostId), Parameters = new object[] {{ {transferParameters} }} }}; module.PostCallMessageAsync(request.Id, MessageType.EventRequest, request); }}; @@ -511,7 +511,7 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()} parametersInsertList.Add("(CancellationToken)special[1]"); break; case "RequestContext": - parametersInsertList.Add("special[1] as RequestContext"); + parametersInsertList.Add("special[0] as RequestContext"); break; default: parametersInsertList.Add(Caster(parameter, diff --git a/mROA/Abstract/IContextRepository.cs b/mROA/Abstract/IContextRepository.cs index 7a3366e..920a317 100644 --- a/mROA/Abstract/IContextRepository.cs +++ b/mROA/Abstract/IContextRepository.cs @@ -9,7 +9,7 @@ namespace mROA.Abstract int ResisterObject(object o, IEndPointContext context); void ClearObject(ComplexObjectIdentifier id); T GetObject(ComplexObjectIdentifier id); - object GetSingleObject(Type type); + object GetSingleObject(Type type, int ownerId); int GetObjectIndex(object o, IEndPointContext context); } } \ No newline at end of file diff --git a/mROA/Abstract/IStorage.cs b/mROA/Abstract/IStorage.cs index 1ba6de3..88432a8 100644 --- a/mROA/Abstract/IStorage.cs +++ b/mROA/Abstract/IStorage.cs @@ -1,8 +1,8 @@ namespace mROA.Abstract { - public interface IStorage + public interface IStorage where T : class { - T GetValue(int index); + T? GetValue(int index); int GetIndex(T value); int Place(T value); void Free(int index); diff --git a/mROA/Implementation/Backend/BasicExecutionModule.cs b/mROA/Implementation/Backend/BasicExecutionModule.cs index 0924999..8b056ba 100644 --- a/mROA/Implementation/Backend/BasicExecutionModule.cs +++ b/mROA/Implementation/Backend/BasicExecutionModule.cs @@ -70,7 +70,7 @@ namespace mROA.Implementation.Backend var context = command.ObjectId.ContextId != -1 ? contextRepository.GetObject(command.ObjectId) - : contextRepository.GetSingleObject(invoker.SuitableType); + : contextRepository.GetSingleObject(invoker.SuitableType, command.ObjectId.OwnerId); if (context == null) throw new NullReferenceException("Instance can't be null"); diff --git a/mROA/Implementation/Backend/ContextRepository.cs b/mROA/Implementation/Backend/ContextRepository.cs index 55b8169..cbc1220 100644 --- a/mROA/Implementation/Backend/ContextRepository.cs +++ b/mROA/Implementation/Backend/ContextRepository.cs @@ -23,26 +23,20 @@ namespace mROA.Implementation.Backend // [CanBeNull] private Dictionary _singletons; - private object?[] _storage; + private IStorage _storage; public ContextRepository() { - _storage = new object[StartupSize]; + _storage = new ExtensibleStorage(); } public int HostId { get; set; } public int ResisterObject(object o, IEndPointContext context) { - if (!_lastIndexFinder.IsCompleted) - _lastIndexFinder.Wait(); + var last = _storage.Place(o); - _storage[_lastIndexFinder.Result] = o; - - - var last = _lastIndexFinder.Result; - _lastIndexFinder = Task.Run(FindLastIndex); EventBinders.OfType>().FirstOrDefault() ?.BindEvents((T)o, context, _representationModuleProducer!, last); @@ -51,18 +45,22 @@ namespace mROA.Implementation.Backend public void ClearObject(ComplexObjectIdentifier id) { - _storage[id.ContextId] = null; - _lastIndexFinder = Task.FromResult(id.ContextId); + _storage.Free(id.ContextId); } public T GetObject(ComplexObjectIdentifier id) { - return id.ContextId == -1 || _storage.Length <= id.ContextId - ? throw new NullReferenceException("Cannot find that object. It is null") - : (T)_storage[id.ContextId]!; + var value = _storage.GetValue(id.ContextId); + + if (value == null) + { + throw new NullReferenceException("Cannot find that object. It is null"); + } + + return (T)value; } - public object GetSingleObject(Type type) + public object GetSingleObject(Type type, int ownerId) { return _singletons.GetValueOrDefault(type.GetHashCode()) ?? throw new ArgumentException("Unregistered singleton type"); @@ -70,7 +68,7 @@ namespace mROA.Implementation.Backend public int GetObjectIndex(object o, IEndPointContext context) { - var index = Array.IndexOf(_storage, o); + var index = _storage.GetIndex(o); return index == -1 ? ResisterObject(o, context) : index; } @@ -93,19 +91,5 @@ namespace mROA.Implementation.Backend i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(), Activator.CreateInstance); } - - private int FindLastIndex() - { - for (var i = 0; i < _storage.Length; i++) - { - if (_storage[i] is null) - return i; - } - - var nextStorage = new object[_storage.Length + GrowSize]; - Array.Copy(_storage, nextStorage, _storage.Length); - _storage = nextStorage; - return _storage.Length; - } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/HubRequestExtractor.cs b/mROA/Implementation/Backend/HubRequestExtractor.cs index 3bad121..4754761 100644 --- a/mROA/Implementation/Backend/HubRequestExtractor.cs +++ b/mROA/Implementation/Backend/HubRequestExtractor.cs @@ -8,6 +8,7 @@ namespace mROA.Implementation.Backend private IConnectionHub? _hub; private IContextRepository? _contextRepository; + private IContextRepository? _remoteContextRepository; private IMethodRepository? _methodRepository; private ISerializationToolkit? _serializationToolkit; private IExecuteModule? _executeModule; @@ -26,8 +27,12 @@ namespace mROA.Implementation.Backend _hub = connectionHub; _hub.OnConnected += HubOnOnConnected; break; - case IContextRepository contextRepository: - _contextRepository = contextRepository; + case MultiClientContextRepository: + case ContextRepository: + _contextRepository = dependency as IContextRepository; + break; + case RemoteContextRepository remoteContextRepository: + _remoteContextRepository = remoteContextRepository; break; case IMethodRepository methodRepository: _methodRepository = methodRepository; @@ -52,6 +57,7 @@ namespace mROA.Implementation.Backend extractor.Inject(_methodRepository); extractor.Inject(_serializationToolkit); extractor.Inject(_executeModule); + extractor.Inject(_remoteContextRepository); _ = extractor.StartExtraction(); } } diff --git a/mROA/Implementation/Backend/MultiClientContextRepository.cs b/mROA/Implementation/Backend/MultiClientContextRepository.cs index 94af7d0..9078788 100644 --- a/mROA/Implementation/Backend/MultiClientContextRepository.cs +++ b/mROA/Implementation/Backend/MultiClientContextRepository.cs @@ -38,10 +38,10 @@ namespace mROA.Implementation.Backend return repository.GetObject(id); } - public object GetSingleObject(Type type) + public object GetSingleObject(Type type, int ownerId) { var repository = GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()); - return repository.GetSingleObject(type); + return repository.GetSingleObject(type, ownerId); } public int GetObjectIndex(object o, IEndPointContext context) diff --git a/mROA/Implementation/ComplexContextRepository.cs b/mROA/Implementation/ComplexContextRepository.cs new file mode 100644 index 0000000..536a36c --- /dev/null +++ b/mROA/Implementation/ComplexContextRepository.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using mROA.Abstract; + +namespace mROA.Implementation +{ + public class ComplexContextRepository : IContextRepository + { + private List>> _storages = new(); + public static object[] EventBinders = { }; + + private IRemoteObjectFactory? _remoteObjectFactory; + private IRepresentationModuleProducer? _representationModuleProducer; + + public void Inject(T dependency) + { + if (dependency is IRemoteObjectFactory remoteObjectFactory) + { + _remoteObjectFactory = remoteObjectFactory; + } + + if (dependency is IRepresentationModuleProducer moduleProducer) + { + _representationModuleProducer = moduleProducer; + } + } + + public int HostId { get; set; } + + public int ResisterObject(object o, IEndPointContext context) + { + var storageIndex = _storages.FindIndex(i => i.Key == context.OwnerId); + if (storageIndex == -1) + { + _storages.Add( + new KeyValuePair>(context.OwnerId, new ExtensibleStorage())); + storageIndex = _storages.Count - 1; + } + + var storage = _storages[storageIndex].Value; + + var placedIndex = storage.Place(o); + EventBinders.OfType>().FirstOrDefault() + ?.BindEvents((T)o, context, _representationModuleProducer!, placedIndex); + + return placedIndex; + } + + public void ClearObject(ComplexObjectIdentifier id) + { + _storages.Find(i => i.Key == id.OwnerId).Value.Free(id.ContextId); + } + + public T GetObject(ComplexObjectIdentifier id) + { + throw new NotImplementedException(); + } + + public object GetSingleObject(Type type, int ownerId) + { + throw new NotImplementedException(); + } + + // public object GetSingleObject(Type type, int ownerId) + // { + // } + + public int GetObjectIndex(object o, IEndPointContext context) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/mROA/Implementation/ComplexRepository.cs b/mROA/Implementation/ComplexRepository.cs deleted file mode 100644 index a46ae58..0000000 --- a/mROA/Implementation/ComplexRepository.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using mROA.Abstract; - -namespace mROA.Implementation -{ - public class ComplexRepository : IContextRepository - { - public void Inject(T dependency) - { - throw new NotImplementedException(); - } - - public int HostId { get; set; } - public int ResisterObject(object o, IEndPointContext context) - { - throw new NotImplementedException(); - } - - public void ClearObject(ComplexObjectIdentifier id) - { - throw new NotImplementedException(); - } - - public T GetObject(ComplexObjectIdentifier id) - { - throw new NotImplementedException(); - } - - public object GetSingleObject(Type type) - { - throw new NotImplementedException(); - } - - public int GetObjectIndex(object o, IEndPointContext context) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/mROA/Implementation/ExtensibleStorage.cs b/mROA/Implementation/ExtensibleStorage.cs index 02d12a4..a9c6d18 100644 --- a/mROA/Implementation/ExtensibleStorage.cs +++ b/mROA/Implementation/ExtensibleStorage.cs @@ -5,16 +5,20 @@ using mROA.Abstract; namespace mROA.Implementation { - public class ExtensibleStorage : IStorage + public class ExtensibleStorage : IStorage where T : class { private const int StartupSize = 1024; private const int GrowSize = 128; private T?[] _array = new T?[StartupSize]; private readonly LinkedList _freePlaces = new(Enumerable.Range(0, StartupSize)); - public T GetValue(int index) + public T? GetValue(int index) { - return _array[index]!; + if (index < 0 || index >= _array.Length) + { + return null; + } + return _array[index]; } public int GetIndex(T value) @@ -31,6 +35,7 @@ namespace mROA.Implementation var index = _freePlaces.First.Value; + _freePlaces.RemoveFirst(); _array[index] = value; return index; diff --git a/mROA/Implementation/Frontend/RequestExtractor.cs b/mROA/Implementation/Frontend/RequestExtractor.cs index 978a4ab..7db7a73 100644 --- a/mROA/Implementation/Frontend/RequestExtractor.cs +++ b/mROA/Implementation/Frontend/RequestExtractor.cs @@ -11,7 +11,8 @@ namespace mROA.Implementation.Frontend { public class RequestExtractor : IRequestExtractor { - private IContextRepository? _contextRepository; + private IContextRepository? _realContextRepository; + private IContextRepository? _remoteContextRepository; private IExecuteModule? _executeModule; private IMethodRepository? _methodRepository; private IRepresentationModule? _representationModule; @@ -24,8 +25,12 @@ namespace mROA.Implementation.Frontend case IExecuteModule executeModule: _executeModule = executeModule; break; - case IContextRepository contextRepository: - _contextRepository = contextRepository; + case MultiClientContextRepository : + case ContextRepository: + _realContextRepository = dependency as IContextRepository; + break; + case RemoteContextRepository remoteContextRepository: + _remoteContextRepository = remoteContextRepository; break; case IMethodRepository methodRepository: _methodRepository = methodRepository; @@ -47,7 +52,7 @@ namespace mROA.Implementation.Frontend throw new NullReferenceException("Serializing toolkit is null."); if (_executeModule == null) throw new NullReferenceException("Execute module is null."); - if (_contextRepository == null) + if (_realContextRepository == null) throw new NullReferenceException("Context repository is null."); if (_representationModule == null) throw new NullReferenceException("Representation module is null."); @@ -89,14 +94,14 @@ namespace mROA.Implementation.Frontend #endif var req = cancelRequest.Result; tokenSource.Cancel(); - _executeModule.Execute(req, _contextRepository, _representationModule); + _executeModule.Execute(req, _realContextRepository, _representationModule); } else if (defaultRequest.IsCompleted) { tokenSource.Cancel(); var request = defaultRequest.Result; - var result = _executeModule.Execute(request, _contextRepository, _representationModule); + var result = _executeModule.Execute(request, _realContextRepository, _representationModule); var resultType = result switch { @@ -112,7 +117,7 @@ namespace mROA.Implementation.Frontend { tokenSource.Cancel(); var request = eventRequest.Result; - _executeModule.Execute(request, _contextRepository, _representationModule); + _executeModule.Execute(request, _remoteContextRepository!, _representationModule); } } } diff --git a/mROA/Implementation/RemoteContextRepository.cs b/mROA/Implementation/RemoteContextRepository.cs index 535db4e..f5d734d 100644 --- a/mROA/Implementation/RemoteContextRepository.cs +++ b/mROA/Implementation/RemoteContextRepository.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Linq; using mROA.Abstract; namespace mROA.Implementation { public class RemoteContextRepository : IContextRepository { + private List _producedRemoteEndpoints = new(); public static Dictionary RemoteTypes = new(); private IRepresentationModuleProducer? _representationProducer; @@ -23,6 +25,9 @@ namespace mROA.Implementation public T GetObject(ComplexObjectIdentifier id) { + var index = _producedRemoteEndpoints.Find(i => i.Identifier.Equals(id)); + if (index is not null) + return (T)(index as object); if (_representationProducer == null) throw new NullReferenceException("representation producer is not initialized"); @@ -31,18 +36,24 @@ namespace mROA.Implementation _representationProducer.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()); var remote = (T)Activator.CreateInstance(remoteType, id.ContextId, representationModule)!; + + _producedRemoteEndpoints.Add((remote as RemoteObjectBase)!); + return remote; } - public object GetSingleObject(Type type) + public object GetSingleObject(Type type, int ownerId) { if (_representationProducer == null) throw new NullReferenceException("representation producer is not initialized"); - + var representationModule = _representationProducer.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()); - return Activator.CreateInstance(RemoteTypes[type], -1, - representationModule)!; + + _producedRemoteEndpoints.Add((Activator.CreateInstance(RemoteTypes[type], -1, + representationModule) as RemoteObjectBase)!); + + return _producedRemoteEndpoints.Last(); } public int GetObjectIndex(object o, IEndPointContext context)