1 //
2 // Copyright (c) 2010-2023 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.Threading;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Exceptions;
12 using Antmicro.Renode.Logging;
13 using Antmicro.Renode.UserInterface;
14 using System.Collections.Concurrent;
15 using Antmicro.Renode.Utilities;
16 using System.IO;
17 
18 namespace Antmicro.Renode
19 {
20     public static class Emulator
21     {
Emulator()22         static Emulator()
23         {
24             UserDirectoryPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create), "renode");
25         }
26 
Exit()27         public static void Exit()
28         {
29             var beforeExit = BeforeExit;
30             if(beforeExit != null)
31             {
32                 try
33                 {
34                     beforeExit();
35                 }
36                 catch (RecoverableException)
37                 {
38                     // Due to a complex bug, such exception is thrown on each exit if GUI was started.
39                     // All OSs are affected, but only Windows logs it. As it looks like a crash and
40                     // Linux/macOS seem to just silence those exceptions anyway, explicit silencing
41                     // seems best for all of them until the real fix is introduced.
42                 }
43             }
44             exitEvent.Set();
45         }
46 
OpenGUI()47         public static void OpenGUI()
48         {
49             if(EnableGUI == null)
50             {
51                 throw new RecoverableException("This feature is available only with interactive Robot tests debug");
52             }
53             EnableGUI();
54         }
55 
CloseGUI()56         public static void CloseGUI()
57         {
58             if(DisableGUI == null)
59             {
60                 throw new RecoverableException("This feature is available only with interactive Robot tests debug");
61             }
62             DisableGUI();
63         }
64 
WaitForExit()65         public static void WaitForExit()
66         {
67             exitEvent.Wait();
68         }
69 
DisposeAll()70         public static void DisposeAll()
71         {
72             if(!disposed)
73             {
74                 disposed = true;
75                 EmulationManager.Instance.Clear();
76                 TypeManager.Instance.Dispose();
77                 Logger.Dispose();
78             }
79         }
80 
81         public static IUserInterfaceProvider UserInterfaceProvider
82         {
83             get
84             {
85                 if(userInterfaceProvider == null)
86                 {
87                     throw new RecoverableException("User interface provider not set");
88                 }
89                 return userInterfaceProvider;
90             }
91             set
92             {
93                 userInterfaceProvider = value;
94             }
95         }
96 
97         public static string UserDirectoryPath
98         {
99             get
100             {
101                 return userDirectoryPath;
102             }
103 
104             set
105             {
106                 userDirectoryPath = value;
107                 Directory.CreateDirectory(userDirectoryPath);
108             }
109         }
110 
111         // CI mode is kind-of-a-hack to allow
112         // running multiple instances of Renode
113         // at the same time by disabling writing
114         // to shared files like binaries cache,
115         // config file, etc.
116         public static bool InCIMode => (Environment.GetEnvironmentVariable("RENODE_CI_MODE") == "YES");
117 
118         private static string userDirectoryPath;
119 
ExecuteOnMainThread(Action what)120         public static void ExecuteOnMainThread(Action what)
121         {
122             actionsOnMainThread.Add(what);
123         }
124 
ExecuteAsMainThread()125         public static void ExecuteAsMainThread()
126         {
127             Action action;
128             while(actionsOnMainThread.TryTake(out action, -1))
129             {
130                 action();
131             }
132         }
133 
FinishExecutionAsMainThread()134         public static void FinishExecutionAsMainThread()
135         {
136             actionsOnMainThread.CompleteAdding();
137         }
138 
139         public static bool ShowAnalyzers { get; set; }
140 
141         private static readonly BlockingCollection<Action> actionsOnMainThread = new BlockingCollection<Action>();
142 
143         public static event Action BeforeExit;
144         public static event Action EnableGUI;
145         public static event Action DisableGUI;
146         private static IUserInterfaceProvider userInterfaceProvider;
147         private static ManualResetEventSlim exitEvent = new ManualResetEventSlim();
148         private static bool disposed;
149     }
150 }
151 
152