1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Text;
|
---|
4 | using HeuristicLab.Core;
|
---|
5 | using HeuristicLab.Data;
|
---|
6 | using HeuristicLab.Communication.Data;
|
---|
7 |
|
---|
8 | namespace HeuristicLab.Communication.Operators {
|
---|
9 | public abstract class CommunicatorBase : OperatorBase {
|
---|
10 | public CommunicatorBase()
|
---|
11 | : base() {
|
---|
12 | AddVariableInfo(new VariableInfo("PeerName", "", typeof(StringData), VariableKind.In));
|
---|
13 | AddVariableInfo(new VariableInfo("Protocol", "", typeof(Protocol), VariableKind.In));
|
---|
14 | AddVariableInfo(new VariableInfo("CurrentState", "", typeof(ProtocolState), VariableKind.In));
|
---|
15 | AddVariableInfo(new VariableInfo("Message", "The message to be sent and/or received. If it is not present the operator will listen for incomming messages.", typeof(Message), VariableKind.New | VariableKind.In | VariableKind.Out | VariableKind.Deleted));
|
---|
16 | }
|
---|
17 |
|
---|
18 | public override IOperation Apply(IScope scope) {
|
---|
19 | Protocol protocol = GetVariableValue<Protocol>("Protocol", scope, true);
|
---|
20 | ProtocolState currentState = GetVariableValue<ProtocolState>("CurrentState", scope, true);
|
---|
21 |
|
---|
22 | IVariableInfo info = GetVariableInfo("Message");
|
---|
23 | string actualName = info.ActualName;
|
---|
24 | if (!info.Local)
|
---|
25 | actualName = scope.TranslateName(info.FormalName);
|
---|
26 |
|
---|
27 | string peerName = GetVariableValue<StringData>("PeerName", scope, true).Data;
|
---|
28 | Message message = GetVariableValue<Message>("Message", scope, false, false);
|
---|
29 |
|
---|
30 | if (message == null) { // RECEIVE MODE (no message present)
|
---|
31 | message = Receive(scope, protocol, currentState);
|
---|
32 | if (message == null) throw new InvalidOperationException("ERROR in Communicator: Message could not be received");
|
---|
33 | if (!info.Local) scope.AddVariable(new Variable(actualName, message));
|
---|
34 | else AddVariable(new Variable(actualName, message));
|
---|
35 | } else { // SEND MODE (message present)
|
---|
36 | if (message.Source.Equals(peerName)) {
|
---|
37 | // originating here, send it
|
---|
38 | Send(scope, protocol, currentState, message);
|
---|
39 | if (!info.Local) scope.RemoveVariable(actualName);
|
---|
40 | else RemoveVariable(actualName);
|
---|
41 | // after sending the message if there is something to be received, apply this operator again
|
---|
42 | if (currentState.Expect.Count > 0) return new AtomicOperation(this, scope);
|
---|
43 | } else throw new ArgumentException("ERROR in Communicator: Message to be sent does not originate from this peer");
|
---|
44 | }
|
---|
45 | return null;
|
---|
46 | }
|
---|
47 |
|
---|
48 | protected abstract void Send(IScope scope, Protocol protocol, ProtocolState currentState, Message message);
|
---|
49 | protected abstract Message Receive(IScope scope, Protocol protocol, ProtocolState currentState);
|
---|
50 | }
|
---|
51 | }
|
---|