diff --git a/Samples/HelloWorld/Client1/Program.cs b/Samples/HelloWorld/Client1/Program.cs index 5feb22b..7cfca92 100644 --- a/Samples/HelloWorld/Client1/Program.cs +++ b/Samples/HelloWorld/Client1/Program.cs @@ -1,5 +1,5 @@ using Ambrosia; -using IClient; +using IClient1; using IServer; using Microsoft.VisualStudio.Threading; using System; @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Client1 { [DataContract] - class Client1 : Immortal, IClient.IClient + class Client1 : Immortal, IClient1.IClient1 { [DataMember] private string _serverName; @@ -50,7 +50,7 @@ namespace Client1 string clientInstanceName = "client1"; string serverInstanceName = "server1"; - using (var c = AmbrosiaFactory.Deploy(clientInstanceName, new Client1(serverInstanceName), receivePort, sendPort)) + using (var c = AmbrosiaFactory.Deploy(clientInstanceName, new Client1(serverInstanceName), receivePort, sendPort)) { finishedTokenQ.DequeueAsync().Wait(); } diff --git a/Samples/HelloWorld/Client2/Client2.csproj b/Samples/HelloWorld/Client2/Client2.csproj new file mode 100644 index 0000000..c6b1d78 --- /dev/null +++ b/Samples/HelloWorld/Client2/Client2.csproj @@ -0,0 +1,18 @@ + + + + Exe + netcoreapp2.0 + AnyCPU;x64 + + + + + + + + + + + + diff --git a/Samples/HelloWorld/Client2/Program.cs b/Samples/HelloWorld/Client2/Program.cs new file mode 100644 index 0000000..f8b0077 --- /dev/null +++ b/Samples/HelloWorld/Client2/Program.cs @@ -0,0 +1,77 @@ +using System; +using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Ambrosia; +using IClient2; +using IServer; +using Microsoft.VisualStudio.Threading; + +namespace Client2 +{ + [DataContract] + class Client2 : Immortal, IClient2.IClient2 + { + [DataMember] + private string _serverName; + + [DataMember] + private IServerProxy _server; + + public Client2(string serverName) + { + _serverName = serverName; + } + + public void IngressKeyboardInput(string input) + { + thisProxy.ReceiveKeyboardInputFork(input); + } + + public async Task ReceiveKeyboardInputAsync(string input) + { + await thisProxy.SendMessageAsync(input); + } + + public async Task SendMessageAsync(string message) + { + Console.WriteLine("Sending message to server: " + message); + int numMessages = await _server.ReceiveMessageAsync(message); + Console.WriteLine("Sent message to server! Server has received " + numMessages + " messages."); + } + + protected override async Task OnFirstStart() + { + _server = GetProxy(_serverName); + return true; + } + } + + class Program + { + public static AsyncQueue finishedTokenQ; + + static void Main(string[] args) + { + finishedTokenQ = new AsyncQueue(); + + int receivePort = 1001; + int sendPort = 1000; + string clientInstanceName = "client2"; + string serverInstanceName = "server1"; + + Client2 client = new Client2(serverInstanceName); + using (var c = AmbrosiaFactory.Deploy(clientInstanceName, client, receivePort, sendPort)) + { + while (finishedTokenQ.IsEmpty) + { + Console.Write("Enter a message (hit ENTER to send): "); + string input = Console.ReadLine(); + client.IngressKeyboardInput(input); + Thread.Sleep(1000); + } + finishedTokenQ.DequeueAsync().Wait(); + } + } + } +} diff --git a/Samples/HelloWorld/Generate-Assemblies-NetCore.ps1 b/Samples/HelloWorld/Generate-Assemblies-NetCore.ps1 index 18dfea5..85ce830 100644 --- a/Samples/HelloWorld/Generate-Assemblies-NetCore.ps1 +++ b/Samples/HelloWorld/Generate-Assemblies-NetCore.ps1 @@ -14,8 +14,11 @@ Write-Host "Using variant of CodeGen.exe: $env:AMBVARIANT" Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=ServerAPI\bin\$env:AMBVARIANT\IServer.dll -o=ServerInterfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0" -Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=IClient\bin\$env:AMBVARIANT\IClient.dll -o=Client1Interfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0" +Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=IClient1\bin\$env:AMBVARIANT\IClient1.dll -o=Client1Interfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0" + +Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=IClient2\bin\$env:AMBVARIANT\IClient2.dll -o=Client2Interfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0" # Generate the assemblies, assumes an .exe which is created by a .Net Framework build: & dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="ServerAPI\bin\$env:AMBVARIANT\IServer.dll" -o=ServerInterfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0" -& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient\bin\$env:AMBVARIANT\IClient.dll" -o=Client1Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0" \ No newline at end of file +& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient1\bin\$env:AMBVARIANT\IClient1.dll" -o=Client1Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0" +& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient2\bin\$env:AMBVARIANT\IClient2.dll" -o=Client2Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0" \ No newline at end of file diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Dispatcher_IClient.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Dispatcher_IClient1.cs similarity index 79% rename from Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Dispatcher_IClient.cs rename to Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Dispatcher_IClient1.cs index fcac017..0631137 100644 --- a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Dispatcher_IClient.cs +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Dispatcher_IClient1.cs @@ -6,29 +6,29 @@ using Ambrosia; using static Ambrosia.StreamCommunicator; using LocalAmbrosiaRuntime; -namespace IClient +namespace IClient1 { /// - /// This class runs in the process of the object that implements the interface IClient + /// This class runs in the process of the object that implements the interface IClient1 /// and communicates with the local Ambrosia runtime. /// It is instantiated in ImmortalFactory.CreateServer when a bootstrapper registers a container - /// that supports the interface IClient. + /// that supports the interface IClient1. /// - class IClient_Dispatcher_Implementation : Immortal.Dispatcher + class IClient1_Dispatcher_Implementation : Immortal.Dispatcher { - private readonly IClient instance; + private readonly IClient1 instance; private readonly ExceptionSerializer exceptionSerializer = new ExceptionSerializer(new List()); - public IClient_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string serviceName, int receivePort, int sendPort, bool setupConnections) + public IClient1_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string serviceName, int receivePort, int sendPort, bool setupConnections) : base(z, myImmortalSerializer, serviceName, receivePort, sendPort, setupConnections) { - this.instance = (IClient) z; + this.instance = (IClient1) z; } - public IClient_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string localAmbrosiaRuntime, Type newInterface, Type newImmortalType, int receivePort, int sendPort) + public IClient1_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string localAmbrosiaRuntime, Type newInterface, Type newImmortalType, int receivePort, int sendPort) : base(z, myImmortalSerializer, localAmbrosiaRuntime, newInterface, newImmortalType, receivePort, sendPort) { - this.instance = (IClient) z; + this.instance = (IClient1) z; } public override async Task DispatchToMethod(int methodId, RpcTypes.RpcType rpcType, string senderOfRPC, long sequenceNumber, byte[] buffer, int cursor) diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ImmortalSerializer.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ImmortalSerializer.cs index f53a2dd..df8d194 100644 --- a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ImmortalSerializer.cs +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ImmortalSerializer.cs @@ -10,7 +10,7 @@ using System.Xml; using Ambrosia; using static Ambrosia.StreamCommunicator; -using IClient; +using IClient1; namespace Ambrosia { @@ -23,7 +23,7 @@ namespace Ambrosia { base.KnownTypes = new SerializableType[] { - new SerializableType(typeof(IClientProxy_Implementation)), + new SerializableType(typeof(IClient1Proxy_Implementation)), new SerializableType(this.GetType()) }; } diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ProxyInterfaces_IClient.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ProxyInterfaces_IClient1.cs similarity index 67% rename from Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ProxyInterfaces_IClient.cs rename to Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ProxyInterfaces_IClient1.cs index ec086b6..4323c19 100644 --- a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ProxyInterfaces_IClient.cs +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/ProxyInterfaces_IClient1.cs @@ -4,23 +4,23 @@ using Ambrosia; using System.Threading.Tasks; using static Ambrosia.StreamCommunicator; -namespace IClient +namespace IClient1 { /// - // Generated from IClient by the proxy generation. + // Generated from IClient1 by the proxy generation. // This is the API that any immortal implementing the interface must be a subtype of. /// - public interface IClient + public interface IClient1 { Task SendMessageAsync(System.String p_0); } /// - // Generated from IClient by the proxy generation. + // Generated from IClient1 by the proxy generation. // This is the API that is used to call a immortal that implements /// - [Ambrosia.InstanceProxy(typeof(IClient))] - public interface IClientProxy + [Ambrosia.InstanceProxy(typeof(IClient1))] + public interface IClient1Proxy { Task SendMessageAsync(System.String p_0); void SendMessageFork(System.String p_0); diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Proxy_IClient.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Proxy_IClient1.cs similarity index 89% rename from Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Proxy_IClient.cs rename to Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Proxy_IClient1.cs index 345798a..9d26ff7 100644 --- a/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Proxy_IClient.cs +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client1Interfaces/latest/Proxy_IClient1.cs @@ -6,24 +6,24 @@ using Ambrosia; using static Ambrosia.StreamCommunicator; -namespace IClient +namespace IClient1 { /// /// This class is the proxy that runs in the client's process and communicates with the local Ambrosia runtime. /// It runs within the client's process, so it is generated in the language that the client is using. - /// It is returned from ImmortalFactory.CreateClient when a client requests a container that supports the interface IClientProxy. + /// It is returned from ImmortalFactory.CreateClient when a client requests a container that supports the interface IClient1Proxy. /// [System.Runtime.Serialization.DataContract] - public class IClientProxy_Implementation : Immortal.InstanceProxy, IClientProxy + public class IClient1Proxy_Implementation : Immortal.InstanceProxy, IClient1Proxy { - public IClientProxy_Implementation(string remoteAmbrosiaRuntime, bool attachNeeded) + public IClient1Proxy_Implementation(string remoteAmbrosiaRuntime, bool attachNeeded) : base(remoteAmbrosiaRuntime, attachNeeded) { } async Task - IClientProxy.SendMessageAsync(System.String p_0) + IClient1Proxy.SendMessageAsync(System.String p_0) { await SendMessageAsync(p_0); } @@ -75,7 +75,7 @@ wp.curLength += arg0Bytes.Length; return; } - void IClientProxy.SendMessageFork(System.String p_0) + void IClient1Proxy.SendMessageFork(System.String p_0) { SerializableTaskCompletionSource rpcTask; diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Client2Interfaces.csproj b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Client2Interfaces.csproj new file mode 100644 index 0000000..c65679a --- /dev/null +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Client2Interfaces.csproj @@ -0,0 +1,15 @@ + + + netcoreapp2.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Dispatcher_IClient2.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Dispatcher_IClient2.cs new file mode 100644 index 0000000..c5c9875 --- /dev/null +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Dispatcher_IClient2.cs @@ -0,0 +1,125 @@ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ambrosia; +using static Ambrosia.StreamCommunicator; +using LocalAmbrosiaRuntime; + +namespace IClient2 +{ + /// + /// This class runs in the process of the object that implements the interface IClient2 + /// and communicates with the local Ambrosia runtime. + /// It is instantiated in ImmortalFactory.CreateServer when a bootstrapper registers a container + /// that supports the interface IClient2. + /// + class IClient2_Dispatcher_Implementation : Immortal.Dispatcher + { + private readonly IClient2 instance; + private readonly ExceptionSerializer exceptionSerializer = new ExceptionSerializer(new List()); + + public IClient2_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string serviceName, int receivePort, int sendPort, bool setupConnections) + : base(z, myImmortalSerializer, serviceName, receivePort, sendPort, setupConnections) + { + this.instance = (IClient2) z; + } + + public IClient2_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string localAmbrosiaRuntime, Type newInterface, Type newImmortalType, int receivePort, int sendPort) + : base(z, myImmortalSerializer, localAmbrosiaRuntime, newInterface, newImmortalType, receivePort, sendPort) + { + this.instance = (IClient2) z; + } + + public override async Task DispatchToMethod(int methodId, RpcTypes.RpcType rpcType, string senderOfRPC, long sequenceNumber, byte[] buffer, int cursor) + { + switch (methodId) + { + case 0: + // Entry point + this.EntryPoint(); + break; + case 1: + // SendMessageAsync + { + // deserialize arguments + + // arg0: System.String + var p_0_ValueLength = buffer.ReadBufferedInt(cursor); +cursor += IntSize(p_0_ValueLength); +var p_0_ValueBuffer = new byte[p_0_ValueLength]; +Buffer.BlockCopy(buffer, cursor, p_0_ValueBuffer, 0, p_0_ValueLength); +cursor += p_0_ValueLength; +var p_0 = Ambrosia.BinarySerializer.Deserialize(p_0_ValueBuffer); + + // call the method + byte[] argExBytes = null; + int argExSize = 0; + Exception currEx = null; + int arg1Size = 0; + byte[] arg1Bytes = null; + + try + { + await this.instance.SendMessageAsync(p_0); + } + catch (Exception ex) + { + currEx = ex; + } + + if (!rpcType.IsFireAndForget()) + { + // serialize result and send it back (there isn't one) + arg1Size = 0; + var wp = this.StartRPC_ReturnValue(senderOfRPC, sequenceNumber, currEx == null ? arg1Size : argExSize, currEx == null ? ReturnValueTypes.EmptyReturnValue : ReturnValueTypes.Exception); + + this.ReleaseBufferAndSend(); + } + } + break; + case 2: + // ReceiveKeyboardInputAsync + { + // deserialize arguments + + // arg0: System.String + var p_0_ValueLength = buffer.ReadBufferedInt(cursor); +cursor += IntSize(p_0_ValueLength); +var p_0_ValueBuffer = new byte[p_0_ValueLength]; +Buffer.BlockCopy(buffer, cursor, p_0_ValueBuffer, 0, p_0_ValueLength); +cursor += p_0_ValueLength; +var p_0 = Ambrosia.BinarySerializer.Deserialize(p_0_ValueBuffer); + + // call the method + byte[] argExBytes = null; + int argExSize = 0; + Exception currEx = null; + int arg1Size = 0; + byte[] arg1Bytes = null; + + try + { + await this.instance.ReceiveKeyboardInputAsync(p_0); + } + catch (Exception ex) + { + currEx = ex; + } + + if (!rpcType.IsFireAndForget()) + { + // serialize result and send it back (there isn't one) + arg1Size = 0; + var wp = this.StartRPC_ReturnValue(senderOfRPC, sequenceNumber, currEx == null ? arg1Size : argExSize, currEx == null ? ReturnValueTypes.EmptyReturnValue : ReturnValueTypes.Exception); + + this.ReleaseBufferAndSend(); + } + } + break; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/ImmortalSerializer.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/ImmortalSerializer.cs new file mode 100644 index 0000000..a91d4a6 --- /dev/null +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/ImmortalSerializer.cs @@ -0,0 +1,70 @@ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading.Tasks; +using System.Threading.Tasks.Dataflow; +using System.Xml; + +using Ambrosia; +using static Ambrosia.StreamCommunicator; +using IClient2; + +namespace Ambrosia +{ + /// + /// This class is the serializer that supports serialization of a Immortal and has the generated classes as a known types + /// ] + public class ImmortalSerializer : ImmortalSerializerBase + { + public ImmortalSerializer() + { + base.KnownTypes = new SerializableType[] + { + new SerializableType(typeof(IClient2Proxy_Implementation)), + new SerializableType(this.GetType()) + }; + } + + public override long SerializeSize(Immortal c) + { + var serializer = new DataContractSerializer(c.GetType(), this.KnownTypes.Select(kt => kt.Type).ToArray()); + long retVal = -1; + using (var countStream = new CountStream()) + { + using (var writer = XmlDictionaryWriter.CreateBinaryWriter(countStream)) + { + serializer.WriteObject(writer, c); + } + retVal = countStream.Length; + } + return retVal; + } + + public override void Serialize(Immortal c, Stream writeToStream) + { + // nned to create + var serializer = new DataContractSerializer(c.GetType(), this.KnownTypes.Select(kt => kt.Type).ToArray()); + using (var writer = XmlDictionaryWriter.CreateBinaryWriter(writeToStream)) + { + serializer.WriteObject(writer, c); + } + } + + public override Immortal Deserialize(Type runtimeType, Stream stream) + { + var serializer = new DataContractSerializer(runtimeType, this.KnownTypes.Select(kt => kt.Type).ToArray()); + using (var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max)) + { + return (Immortal)serializer.ReadObject(reader); + } + } + } + + public interface Empty : IEmpty + { + + } +} \ No newline at end of file diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/ProxyInterfaces_IClient2.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/ProxyInterfaces_IClient2.cs new file mode 100644 index 0000000..8731d5e --- /dev/null +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/ProxyInterfaces_IClient2.cs @@ -0,0 +1,30 @@ + +using System; +using Ambrosia; +using System.Threading.Tasks; +using static Ambrosia.StreamCommunicator; + +namespace IClient2 +{ + /// + // Generated from IClient2 by the proxy generation. + // This is the API that any immortal implementing the interface must be a subtype of. + /// + public interface IClient2 + { + Task SendMessageAsync(System.String p_0); + Task ReceiveKeyboardInputAsync(System.String p_0); + } + + /// + // Generated from IClient2 by the proxy generation. + // This is the API that is used to call a immortal that implements + /// + [Ambrosia.InstanceProxy(typeof(IClient2))] + public interface IClient2Proxy + { + Task SendMessageAsync(System.String p_0); + void SendMessageFork(System.String p_0); + void ReceiveKeyboardInputFork(System.String p_0); + } +} \ No newline at end of file diff --git a/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Proxy_IClient2.cs b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Proxy_IClient2.cs new file mode 100644 index 0000000..a574e24 --- /dev/null +++ b/Samples/HelloWorld/GeneratedSourceFiles/Client2Interfaces/latest/Proxy_IClient2.cs @@ -0,0 +1,156 @@ + +using System; +using System.Threading.Tasks; +using System.Threading.Tasks.Dataflow; +using Ambrosia; +using static Ambrosia.StreamCommunicator; + + +namespace IClient2 +{ + /// + /// This class is the proxy that runs in the client's process and communicates with the local Ambrosia runtime. + /// It runs within the client's process, so it is generated in the language that the client is using. + /// It is returned from ImmortalFactory.CreateClient when a client requests a container that supports the interface IClient2Proxy. + /// + [System.Runtime.Serialization.DataContract] + public class IClient2Proxy_Implementation : Immortal.InstanceProxy, IClient2Proxy + { + + public IClient2Proxy_Implementation(string remoteAmbrosiaRuntime, bool attachNeeded) + : base(remoteAmbrosiaRuntime, attachNeeded) + { + } + + async Task + IClient2Proxy.SendMessageAsync(System.String p_0) + { + await SendMessageAsync(p_0); + } + + async Task + SendMessageAsync(System.String p_0) + { + SerializableTaskCompletionSource rpcTask; + // Make call, wait for reply + // Compute size of serialized arguments + var totalArgSize = 0; + + int arg0Size = 0; + byte[] arg0Bytes = null; + + // Argument 0 + arg0Bytes = Ambrosia.BinarySerializer.Serialize(p_0); +arg0Size = IntSize(arg0Bytes.Length) + arg0Bytes.Length; + + totalArgSize += arg0Size; + + var wp = this.StartRPC(methodIdentifier: 1 /* method identifier for SendMessage */, lengthOfSerializedArguments: totalArgSize, taskToWaitFor: out rpcTask); + var asyncContext = new AsyncContext { SequenceNumber = Immortal.CurrentSequenceNumber }; + + // Serialize arguments + + + // Serialize arg0 + wp.curLength += wp.PageBytes.WriteInt(wp.curLength, arg0Bytes.Length); +Buffer.BlockCopy(arg0Bytes, 0, wp.PageBytes, wp.curLength, arg0Bytes.Length); +wp.curLength += arg0Bytes.Length; + + + ReleaseBufferAndSend(); + + var taskToWaitFor = Immortal.CallCache.Data[asyncContext.SequenceNumber].GetAwaitableTaskWithAdditionalInfoAsync(); + var currentResult = await taskToWaitFor; + + var isSaved = await Immortal.TrySaveContextContinuationAsync(currentResult); + + if (isSaved) + { + taskToWaitFor = Immortal.CallCache.Data[asyncContext.SequenceNumber].GetAwaitableTaskWithAdditionalInfoAsync(); + currentResult = await taskToWaitFor; + } + + await Immortal.TryTakeCheckpointContinuationAsync(currentResult); + + return; + } + + void IClient2Proxy.SendMessageFork(System.String p_0) + { + SerializableTaskCompletionSource rpcTask; + + // Compute size of serialized arguments + var totalArgSize = 0; + + // Argument 0 + int arg0Size = 0; + byte[] arg0Bytes = null; + + arg0Bytes = Ambrosia.BinarySerializer.Serialize(p_0); +arg0Size = IntSize(arg0Bytes.Length) + arg0Bytes.Length; + + totalArgSize += arg0Size; + + var wp = this.StartRPC(1 /* method identifier for SendMessage */, totalArgSize, out rpcTask, RpcTypes.RpcType.FireAndForget); + + // Serialize arguments + + + // Serialize arg0 + wp.curLength += wp.PageBytes.WriteInt(wp.curLength, arg0Bytes.Length); +Buffer.BlockCopy(arg0Bytes, 0, wp.PageBytes, wp.curLength, arg0Bytes.Length); +wp.curLength += arg0Bytes.Length; + + + this.ReleaseBufferAndSend(); + return; + } + + private object + SendMessage_ReturnValue(byte[] buffer, int cursor) + { + // buffer will be an empty byte array since the method SendMessage returns void + // so nothing to read, just getting called is the signal to return to the client + return this; + } + + void IClient2Proxy.ReceiveKeyboardInputFork(System.String p_0) + { + SerializableTaskCompletionSource rpcTask; + + // Compute size of serialized arguments + var totalArgSize = 0; + + // Argument 0 + int arg0Size = 0; + byte[] arg0Bytes = null; + + arg0Bytes = Ambrosia.BinarySerializer.Serialize(p_0); +arg0Size = IntSize(arg0Bytes.Length) + arg0Bytes.Length; + + totalArgSize += arg0Size; + + var wp = this.StartRPC(2 /* method identifier for ReceiveKeyboardInput */, totalArgSize, out rpcTask, RpcTypes.RpcType.Impulse); + + // Serialize arguments + + + // Serialize arg0 + wp.curLength += wp.PageBytes.WriteInt(wp.curLength, arg0Bytes.Length); +Buffer.BlockCopy(arg0Bytes, 0, wp.PageBytes, wp.curLength, arg0Bytes.Length); +wp.curLength += arg0Bytes.Length; + + + this.ReleaseBufferAndSend(); + return; + } + + private object + ReceiveKeyboardInput_ReturnValue(byte[] buffer, int cursor) + { + // buffer will be an empty byte array since the method ReceiveKeyboardInput returns void + // so nothing to read, just getting called is the signal to return to the client + return this; + } + } +} \ No newline at end of file diff --git a/Samples/HelloWorld/HelloWorld.sln b/Samples/HelloWorld/HelloWorld.sln index f6d51e0..e22ffaf 100644 --- a/Samples/HelloWorld/HelloWorld.sln +++ b/Samples/HelloWorld/HelloWorld.sln @@ -13,7 +13,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerInterfaces", "Generat EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client1Interfaces", "GeneratedSourceFiles\Client1Interfaces\latest\Client1Interfaces.csproj", "{625A71B0-DA9E-467F-9744-A4344EA8B6E5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IClient", "IClient\IClient.csproj", "{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IClient2", "IClient2\IClient2.csproj", "{975C3389-6CE2-4905-BE58-57FCF29B5D31}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client2", "Client2\Client2.csproj", "{644D897D-1311-4073-9F0C-4197A9719E28}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client2Interfaces", "GeneratedSourceFiles\Client2Interfaces\latest\Client2Interfaces.csproj", "{6E5C78F0-B847-4C22-90B6-FAA96C013609}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IClient1", "IClient1\IClient1.csproj", "{8EFAD205-E2BF-46C0-B310-7D023210797F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -57,14 +63,38 @@ Global {625A71B0-DA9E-467F-9744-A4344EA8B6E5}.Release|Any CPU.Build.0 = Release|Any CPU {625A71B0-DA9E-467F-9744-A4344EA8B6E5}.Release|x64.ActiveCfg = Release|Any CPU {625A71B0-DA9E-467F-9744-A4344EA8B6E5}.Release|x64.Build.0 = Release|Any CPU - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|x64.ActiveCfg = Debug|x64 - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|x64.Build.0 = Debug|x64 - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|Any CPU.Build.0 = Release|Any CPU - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|x64.ActiveCfg = Release|Any CPU - {F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|x64.Build.0 = Release|Any CPU + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|Any CPU.Build.0 = Debug|Any CPU + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|x64.ActiveCfg = Debug|x64 + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|x64.Build.0 = Debug|x64 + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|Any CPU.ActiveCfg = Release|Any CPU + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|Any CPU.Build.0 = Release|Any CPU + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|x64.ActiveCfg = Release|Any CPU + {975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|x64.Build.0 = Release|Any CPU + {644D897D-1311-4073-9F0C-4197A9719E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {644D897D-1311-4073-9F0C-4197A9719E28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {644D897D-1311-4073-9F0C-4197A9719E28}.Debug|x64.ActiveCfg = Debug|x64 + {644D897D-1311-4073-9F0C-4197A9719E28}.Debug|x64.Build.0 = Debug|x64 + {644D897D-1311-4073-9F0C-4197A9719E28}.Release|Any CPU.ActiveCfg = Release|Any CPU + {644D897D-1311-4073-9F0C-4197A9719E28}.Release|Any CPU.Build.0 = Release|Any CPU + {644D897D-1311-4073-9F0C-4197A9719E28}.Release|x64.ActiveCfg = Release|Any CPU + {644D897D-1311-4073-9F0C-4197A9719E28}.Release|x64.Build.0 = Release|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|x64.ActiveCfg = Debug|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|x64.Build.0 = Debug|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|Any CPU.Build.0 = Release|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|x64.ActiveCfg = Release|Any CPU + {6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|x64.Build.0 = Release|Any CPU + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|x64.ActiveCfg = Debug|x64 + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|x64.Build.0 = Debug|x64 + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|Any CPU.Build.0 = Release|Any CPU + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|x64.ActiveCfg = Release|x64 + {8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/HelloWorld/IClient/IClient.cs b/Samples/HelloWorld/IClient1/IClient1.cs similarity index 60% rename from Samples/HelloWorld/IClient/IClient.cs rename to Samples/HelloWorld/IClient1/IClient1.cs index 852259c..e10211b 100644 --- a/Samples/HelloWorld/IClient/IClient.cs +++ b/Samples/HelloWorld/IClient1/IClient1.cs @@ -1,8 +1,8 @@ using System; -namespace IClient +namespace IClient1 { - public interface IClient + public interface IClient1 { void SendMessage(string message); } diff --git a/Samples/HelloWorld/IClient/IClient.csproj b/Samples/HelloWorld/IClient1/IClient1.csproj similarity index 67% rename from Samples/HelloWorld/IClient/IClient.csproj rename to Samples/HelloWorld/IClient1/IClient1.csproj index 8c5b326..8970b0c 100644 --- a/Samples/HelloWorld/IClient/IClient.csproj +++ b/Samples/HelloWorld/IClient1/IClient1.csproj @@ -3,6 +3,8 @@ netcoreapp2.0 AnyCPU;x64 + IClient1 + IClient1 diff --git a/Samples/HelloWorld/IClient2/IClient2.cs b/Samples/HelloWorld/IClient2/IClient2.cs new file mode 100644 index 0000000..6e5e517 --- /dev/null +++ b/Samples/HelloWorld/IClient2/IClient2.cs @@ -0,0 +1,13 @@ +using Ambrosia; +using System; + +namespace IClient2 +{ + public interface IClient2 + { + void SendMessage(string message); + + [ImpulseHandler] + void ReceiveKeyboardInput(string message); + } +} diff --git a/Samples/HelloWorld/IClient2/IClient2.csproj b/Samples/HelloWorld/IClient2/IClient2.csproj new file mode 100644 index 0000000..cc5f3ba --- /dev/null +++ b/Samples/HelloWorld/IClient2/IClient2.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp2.0 + AnyCPU;x64 + + + + + + +