1 // 2 // Copyright (c) 2010-2018 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.Collections.Generic; 10 using System.Threading; 11 using System.Linq; 12 13 namespace Antmicro.Renode.Utilities 14 { 15 public class ProgressMonitor 16 { Start(string description, bool cancelable = false, bool progressable = false)17 public MonitoredAction Start(string description, bool cancelable = false, bool progressable = false) 18 { 19 lock(locker) 20 { 21 var threadId = Thread.CurrentThread.ManagedThreadId; 22 if(!runningActions.ContainsKey(threadId)) 23 { 24 runningActions.Add(threadId, new Stack<MonitoredAction>()); 25 } 26 27 var actions = runningActions[threadId]; 28 var action = new MonitoredAction(this, description, cancelable, progressable); 29 actions.Push(action); 30 31 UpdateDialog(); 32 33 return action; 34 } 35 } 36 Stop()37 public void Stop() 38 { 39 lock(locker) 40 { 41 while (runningActions.Count > 0) 42 { 43 var kvp = runningActions.First(); 44 while(kvp.Value.Count > 0) 45 { 46 var a = kvp.Value.Pop(); 47 a.Finish(); 48 } 49 } 50 } 51 } 52 UpdateDialog()53 private void UpdateDialog() 54 { 55 lock(locker) 56 { 57 var h = Handler; 58 var actionsToRemove = new List<int>(); 59 foreach(var action in runningActions) 60 { 61 MonitoredAction current = null; 62 while(true) 63 { 64 current = action.Value.Count > 0 ? action.Value.Peek() : null; 65 if(current != null && current.IsFinished) 66 { 67 action.Value.Pop(); 68 continue; 69 } 70 break; 71 } 72 73 if(current == null) 74 { 75 actionsToRemove.Add(action.Key); 76 if(h != null) 77 { 78 h.Finish(action.Key); 79 } 80 continue; 81 } 82 83 if(h != null) 84 { 85 h.Update(action.Key, current.Description, current.Progress); 86 } 87 } 88 89 foreach(var actionToRemove in actionsToRemove) 90 { 91 runningActions.Remove(actionToRemove); 92 } 93 } 94 } 95 96 private Dictionary<int, Stack<MonitoredAction>> runningActions = new Dictionary<int, Stack<MonitoredAction>>(); 97 98 private object locker = new object(); 99 100 public IProgressMonitorHandler Handler { get; set; } 101 102 public class MonitoredAction : IDisposable 103 { MonitoredAction(ProgressMonitor monitor, string description, bool cancelable, bool progressable)104 public MonitoredAction(ProgressMonitor monitor, string description, bool cancelable, bool progressable) 105 { 106 this.monitor = monitor; 107 Description = description; 108 IsCancelable = cancelable; 109 110 Progress = progressable ? (int?)0 : null; 111 } 112 UpdateProgress(int progress, string description = null)113 public void UpdateProgress(int progress, string description = null) 114 { 115 Progress = progress; 116 if(description != null) 117 { 118 Description = description; 119 } 120 121 if(progress == 100) 122 { 123 IsFinished = true; 124 } 125 126 monitor.UpdateDialog(); 127 } 128 Finish()129 public void Finish() 130 { 131 IsFinished = true; 132 monitor.UpdateDialog(); 133 } 134 Dispose()135 public void Dispose() 136 { 137 Finish(); 138 } 139 140 public bool IsCancelable { get; private set; } 141 public bool IsFinished { get; private set; } 142 public int? Progress { get; private set; } 143 public string Description { get; private set; } 144 145 private ProgressMonitor monitor; 146 } 147 } 148 } 149 150