2 using System.Threading;
3 using System.Collections.Generic;
5 namespace Mono.Debugger.Soft
7 public class ThreadMirror : ObjectMirror
10 bool cacheInvalid = true;
12 object fetchingLocker = new object ();
13 ManualResetEvent fetchingEvent = new ManualResetEvent (false);
17 internal ThreadMirror (VirtualMachine vm, long id) : base (vm, id) {
20 internal ThreadMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id, type, domain) {
23 public StackFrame[] GetFrames () {
25 fetchingEvent.WaitOne ();
29 internal void InvalidateFrames () {
33 internal void FetchFrames (bool mustFetch = false) {
34 lock (fetchingLocker) {
35 if (fetching || !cacheInvalid)
39 fetchingEvent.Reset ();
41 vm.conn.Thread_GetFrameInfo (id, 0, -1, (frame_info) => {
42 var framesList = new List<StackFrame> ();
43 for (int i = 0; i < frame_info.Length; ++i) {
44 var frameInfo = (FrameInfo)frame_info [i];
45 var method = vm.GetMethod (frameInfo.method);
46 var f = new StackFrame (vm, frameInfo.id, this, method, frameInfo.il_offset, frameInfo.flags);
47 if (!(f.IsNativeTransition && !NativeTransitions))
50 lock (fetchingLocker) {
51 vm.AddThreadToInvalidateList (this);
53 //In case it was invalidated during waiting for response from
54 //runtime and mustFetch was set refetch
55 if (cacheInvalid && mustFetch) {
56 FetchFrames (mustFetch);
59 frames = framesList.ToArray ();
65 public static void FetchFrames(IList<ThreadMirror> threads)
67 if (threads.Count == 0)
69 threads [0].vm.conn.StartBuffering ();
70 foreach (var thread in threads) {
71 thread.FetchFrames ();
73 threads [0].vm.conn.StopBuffering ();
79 name = vm.conn.Thread_GetName (id);
90 public ThreadState ThreadState {
92 return (ThreadState)vm.conn.Thread_GetState (id);
96 public bool IsThreadPoolThread {
99 info = vm.conn.Thread_GetInfo (id);
100 return info.is_thread_pool;
106 * Return a unique identifier for this thread, multiple ThreadMirror objects
107 * may have the same ThreadId because of appdomains.
109 public long ThreadId {
111 if (thread_id == null)
112 thread_id = vm.conn.Thread_GetId (id);
113 return (long)thread_id;
118 * Return the system thread id (TID) for this thread, this id is not unique since
119 * a newly started thread might reuse a dead thread's id.
123 return vm.conn.Thread_GetTID (id);
128 * Get/set whenever GetFrames () should return frames for managed-to-native
129 * transitions, i.e frames whose IsNativeTransition property is set.
130 * This is needed because some clients might not be able to deal with those
133 public static bool NativeTransitions {
138 * Set the location where execution will return when this thread is
141 * ArgumentException - if L doesn't refer to a location in the
142 * current method of this thread.
143 * NotSupportedException - if continuing at L is not supported
144 * for any other reason.
145 * Since protocol version 29.
147 public void SetIP (Location loc) {
149 throw new ArgumentNullException ("loc");
151 vm.conn.Thread_SetIP (id, loc.Method.Id, loc.ILOffset);
152 } catch (CommandException ex) {
153 if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
154 throw new ArgumentException ("loc doesn't refer to a location in the current method of this thread.", "loc");