2 using System.Collections.Generic;
5 using SiliconStudio.Paradox.Framework;
6 using SiliconStudio.Paradox.Framework.MicroThreading;
7 using SiliconStudio.Core.Extensions;
8 using System.Diagnostics;
9 using System.Threading;
10 using SiliconStudio.Paradox.Framework.Time;
11 using SiliconStudio.Paradox.DebugTools.DataStructures;
12 using SiliconStudio.Presentation.Observable;
14 namespace SiliconStudio.
Paradox.DebugTools
26 public const int MaximumCapturedFrames = 30;
28 public Scheduler Scheduler {
get;
private set; }
29 public uint CurrentFrameNumber {
get {
return frameNumber; } }
31 private readonly AbsoluteStopwatch stopwatch =
new AbsoluteStopwatch();
32 private readonly ObserverContainer<FrameInfo> observerContainer =
new ObserverContainer<FrameInfo>();
34 private readonly
object processInfoLock =
new object();
37 private uint frameNumber;
39 private readonly Dictionary<long, MicroThreadPendingState> pendingMicroThreads =
new Dictionary<long, MicroThreadPendingState>();
43 if (scheduler == null)
44 throw new ArgumentNullException(
"scheduler");
46 Scheduler = scheduler;
54 public IDisposable
Subscribe(IObserver<FrameInfo> observer)
56 return observerContainer.Subscribe(observer);
67 throw new NotImplementedException();
79 throw new NotImplementedException();
91 lock (processInfoLock)
118 lock (processInfoLock)
120 duplicate = processInfo.Duplicate();
126 private void OnMicroThreadStateChanged(
object sender, SchedulerEventArgs e)
131 if (frameInfo == null)
134 double currentTime = stopwatch.Elapsed;
136 int threadId = Thread.CurrentThread.ManagedThreadId;
137 long microThreadId = e.MicroThread.Id;
139 ThreadInfo threadInfo = frameInfo.ThreadItems.FirstOrDefault(ti => ti.Id == threadId);
140 if (threadInfo == null)
142 threadInfo =
new ThreadInfo { Id = threadId };
143 frameInfo.ThreadItems.Add(threadInfo);
148 MicroThreadPendingState pendingState;
149 if (pendingMicroThreads.TryGetValue(microThreadId, out pendingState))
154 BeginState = pendingState.State,
155 EndState = e.MicroThread.State,
156 BeginTime = Math.Max(pendingState.Time, frameInfo.BeginTime),
157 EndTime = currentTime,
160 pendingMicroThreads.Remove(microThreadId);
162 else if (e.MicroThread.IsOver ==
false)
164 pendingMicroThreads.Add(microThreadId,
new MicroThreadPendingState
166 ThreadId = threadInfo.Id,
168 State = e.MicroThread.State,
169 MicroThread = e.MicroThread,
174 private void OnMessageLoopBegin(
object sender,
EventArgs e)
176 double currentTime = stopwatch.Elapsed;
178 if (frameInfo != null)
180 frameInfo.EndTime = currentTime;
182 foreach (MicroThreadPendingState pendingState
in pendingMicroThreads.Values)
184 ThreadInfo th = frameInfo.ThreadItems.FirstOrDefault(ti => ti.Id == pendingState.ThreadId);
186 throw new InvalidOperationException(
"Thread " + pendingState.ThreadId +
" is not referenced in frame " + frameInfo.FrameNumber);
190 Id = pendingState.MicroThread.Id,
191 BeginState = pendingState.State,
192 EndState = pendingState.State,
193 BeginTime = Math.Max(pendingState.Time, frameInfo.BeginTime),
194 EndTime = currentTime,
199 lock (observerContainer.SyncRoot)
201 observerContainer.Observers.ForEach(observer => observer.OnNext(frameInfo));
205 lock (processInfoLock)
207 processInfo.Frames.Add(frameInfo);
213 BeginTime = currentTime,
214 FrameNumber = frameNumber++,
217 lock (processInfoLock)
219 if (processInfo.Frames.Count > MaximumCapturedFrames)
220 processInfo.Frames.RemoveAt(0);