1 //
2 // Copyright (c) 2010-2018 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Threading;
9 using System.Collections.Generic;
10 using System.Collections.Concurrent;
11 using Antmicro.Renode.Utilities;
12 
13 namespace Antmicro.Renode.Time
14 {
15     /// <summary>
16     /// Represents a helper class used to obtain a virtual time stamp of a current thread.
17     /// </summary>
18     public class TimeDomainsManager
19     {
20         public static TimeDomainsManager Instance = new TimeDomainsManager();
21 
22         /// <summary>
23         /// Registers a time stamp provider for the current thread.
24         /// </summary>
RegisterCurrentThread(Func<TimeStamp> f)25         public IDisposable RegisterCurrentThread(Func<TimeStamp> f)
26         {
27             timeGetters.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, f, (k, v) => f);
28             return new DisposableWrapper().RegisterDisposeAction(() => Instance.UnregisterCurrentThread());
29         }
30 
31         /// <summary>
32         /// Unregisters a time stamp provider for the current thread.
33         /// </summary>
UnregisterCurrentThread()34         public void UnregisterCurrentThread()
35         {
36             var result = timeGetters.TryRemove(Thread.CurrentThread.ManagedThreadId, out var unused);
37             Renode.Debugging.DebugHelper.Assert(result, "Tried to unregister an unregistered thread.");
38         }
39 
40         /// <summary>
41         /// Returns virtual time stamp for the current thread.
42         /// </summary>
43         public TimeStamp VirtualTimeStamp
44         {
45             get
46             {
47                 if(!timeGetters.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var timestampGenerator))
48                 {
49                     throw new ArgumentException($"Tried to obtain a virtual time stamp of an unregistered thread: '{Thread.CurrentThread.Name}'/{Thread.CurrentThread.ManagedThreadId}");
50                 }
51                 return timestampGenerator();
52             }
53         }
54 
55         /// <summary>
56         /// Tries to obtain virtual time stamp for the current thread.
57         /// </summary>
58         /// <returns><c>true</c>, if virtual time stamp was obtained, <c>false</c> otherwise.</returns>
59         /// <param name="virtualTimeStamp">Virtual time stamp.</param>
TryGetVirtualTimeStamp(out TimeStamp virtualTimeStamp)60         public bool TryGetVirtualTimeStamp(out TimeStamp virtualTimeStamp)
61         {
62             if(!timeGetters.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var timestampGenerator))
63             {
64                 virtualTimeStamp = default(TimeStamp);
65                 return false;
66             }
67             virtualTimeStamp = timestampGenerator();
68             return true;
69         }
70 
TimeDomainsManager()71         private TimeDomainsManager()
72         {
73             timeGetters = new ConcurrentDictionary<int, Func<TimeStamp>>();
74         }
75 
76         private readonly ConcurrentDictionary<int, Func<TimeStamp>> timeGetters;
77     }
78 }
79