1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System.Collections.Generic;
9 using Antmicro.Renode.Core;
10 using Antmicro.Renode.Exceptions;
11 using Antmicro.Renode.Peripherals;
12 using Antmicro.Renode.Time;
13 
14 namespace Antmicro.Renode.Network
15 {
16     public class BasicNetwork<TData, TAddress> : IExternal, IConnectable<IBasicNetworkNode<TData, TAddress>>
17     {
BasicNetwork(string name)18         public BasicNetwork(string name)
19         {
20             this.sync = new object();
21             this.name = name;
22             nodes = new List<IBasicNetworkNode<TData, TAddress>>();
23         }
24 
AttachTo(IBasicNetworkNode<TData, TAddress> node)25         public void AttachTo(IBasicNetworkNode<TData, TAddress> node)
26         {
27             lock(sync)
28             {
29                 if(nodes.Contains(node))
30                 {
31                     throw new RecoverableException($"Provided node is already registered in network '{name}'");
32                 }
33 
34                 node.TrySendData += SendData;
35                 nodes.Add(node);
36             }
37         }
38 
DetachFrom(IBasicNetworkNode<TData, TAddress> node)39         public void DetachFrom(IBasicNetworkNode<TData, TAddress> node)
40         {
41             lock(sync)
42             {
43                 if(nodes.Remove(node))
44                 {
45                     node.TrySendData -= SendData;
46                     return;
47                 }
48 
49                 throw new RecoverableException($"Provided node is not registered in network '{name}' and cannot be detached from it");
50             }
51         }
52 
SendData(TData data, TAddress source, TAddress destination)53         private bool SendData(TData data, TAddress source, TAddress destination)
54         {
55             var dataSent = false;
56             foreach(var node in GetMatchingNodes(destination))
57             {
58                 node.GetMachine().HandleTimeDomainEvent<object>((_) => node.ReceiveData(data, source, destination), null, TimeDomainsManager.Instance.VirtualTimeStamp);
59                 dataSent = true;
60             }
61             return dataSent;
62         }
63 
GetMatchingNodes(TAddress address)64         private IEnumerable<IBasicNetworkNode<TData, TAddress>> GetMatchingNodes(TAddress address)
65         {
66             lock(sync)
67             {
68                 foreach(var node in nodes)
69                 {
70                     if(address.Equals(node.NodeAddress))
71                     {
72                         yield return node;
73                     }
74                 }
75             }
76         }
77 
78         private readonly List<IBasicNetworkNode<TData, TAddress>> nodes;
79         private readonly string name;
80         private readonly object sync;
81     }
82 }
83