2 using System.Collections.Generic;
3 using System.Runtime.Remoting.Messaging;
4 using System.Threading;
6 namespace Mono.Debugger.Soft
8 public class ObjectMirror : Value {
10 AppDomainMirror domain;
12 internal ObjectMirror (VirtualMachine vm, long id) : base (vm, id) {
15 internal ObjectMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id) {
21 var info = vm.conn.Object_GetInfo (id);
22 type = vm.GetType (info.type_id);
23 domain = vm.GetDomain (info.domain_id);
26 public TypeMirror Type {
29 if (vm.conn.Version.AtLeast (2, 5))
32 type = vm.GetType (vm.conn.Object_GetType (id));
38 public AppDomainMirror Domain {
41 if (vm.conn.Version.AtLeast (2, 5))
44 domain = vm.GetDomain (vm.conn.Object_GetDomain (id));
50 public bool IsCollected {
52 return vm.conn.Object_IsCollected (id);
56 public Value GetValue (FieldInfoMirror field) {
57 return GetValues (new FieldInfoMirror [] { field }) [0];
60 public Value[] GetValues (IList<FieldInfoMirror> fields) {
62 throw new ArgumentNullException ("fields");
63 foreach (FieldInfoMirror f in fields) {
65 throw new ArgumentNullException ("field");
68 long[] ids = new long [fields.Count];
69 for (int i = 0; i < fields.Count; ++i)
70 ids [i] = fields [i].Id;
72 return vm.DecodeValues (vm.conn.Object_GetValues (id, ids));
73 } catch (CommandException ex) {
74 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
75 throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
81 public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
83 throw new ArgumentNullException ("fields");
85 throw new ArgumentNullException ("values");
86 foreach (FieldInfoMirror f in fields) {
88 throw new ArgumentNullException ("field");
91 foreach (Value v in values) {
93 throw new ArgumentNullException ("values");
96 long[] ids = new long [fields.Count];
97 for (int i = 0; i < fields.Count; ++i)
98 ids [i] = fields [i].Id;
100 vm.conn.Object_SetValues (id, ids, vm.EncodeValues (values));
101 } catch (CommandException ex) {
102 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
103 throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
104 else if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
105 throw new ArgumentException ("One of the values is not valid for its field.", "values");
111 public void SetValue (FieldInfoMirror field, Value value) {
112 SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
116 * The current address of the object. It can change during garbage
117 * collections. Use a long since the debuggee might have a different
120 public long Address {
122 return vm.conn.Object_GetAddress (id);
126 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
127 return InvokeMethod (vm, thread, method, this, arguments, InvokeOptions.None);
130 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
131 return InvokeMethod (vm, thread, method, this, arguments, options);
134 [Obsolete ("Use the overload without the 'vm' argument")]
135 public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
136 return BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
139 public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
140 return BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
143 public Value EndInvokeMethod (IAsyncResult asyncResult) {
144 return EndInvokeMethodInternal (asyncResult);
148 // Invoke the members of METHODS one-by-one, calling CALLBACK after each invoke was finished. The IAsyncResult will be marked as completed after all invokes have
149 // finished. The callback will be called with a different IAsyncResult that represents one method invocation.
150 // From protocol version 2.22.
152 public IAsyncResult BeginInvokeMultiple (ThreadMirror thread, MethodMirror[] methods, IList<IList<Value>> arguments, InvokeOptions options, AsyncCallback callback, object state) {
153 return BeginInvokeMultiple (vm, thread, methods, this, arguments, options, callback, state);
156 public void EndInvokeMultiple (IAsyncResult asyncResult) {
157 EndInvokeMultipleInternal (asyncResult);
161 * Common implementation for invokes
164 class InvokeAsyncResult : IInvokeAsyncResult {
166 public object AsyncState {
170 public WaitHandle AsyncWaitHandle {
174 public bool CompletedSynchronously {
180 public bool IsCompleted {
184 public AsyncCallback Callback {
188 public ErrorCode ErrorCode {
192 public VirtualMachine VM {
196 public ThreadMirror Thread {
200 public ValueImpl Value {
204 public ValueImpl Exception {
212 public bool IsMultiple {
216 public int NumPending;
220 if (ID == 0) // Ooops
223 ObjectMirror.AbortInvoke (VM, Thread, ID);
227 internal static IInvokeAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, Value this_obj, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
229 throw new ArgumentNullException ("thread");
231 throw new ArgumentNullException ("method");
232 if (arguments == null)
233 arguments = new Value [0];
235 InvokeFlags f = InvokeFlags.NONE;
237 if ((options & InvokeOptions.DisableBreakpoints) != 0)
238 f |= InvokeFlags.DISABLE_BREAKPOINTS;
239 if ((options & InvokeOptions.SingleThreaded) != 0)
240 f |= InvokeFlags.SINGLE_THREADED;
242 InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback };
244 r.ID = vm.conn.VM_BeginInvokeMethod (thread.Id, method.Id, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), vm.EncodeValues (arguments), f, InvokeCB, r);
249 // This is called when the result of an invoke is received
250 static void InvokeCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) {
251 InvokeAsyncResult r = (InvokeAsyncResult)state;
260 r.IsCompleted = true;
261 ((ManualResetEvent)r.AsyncWaitHandle).Set ();
263 if (r.Callback != null)
264 r.Callback.BeginInvoke (r, null, null);
267 internal static Value EndInvokeMethodInternal (IAsyncResult asyncResult) {
268 if (asyncResult == null)
269 throw new ArgumentNullException ("asyncResult");
271 InvokeAsyncResult r = (InvokeAsyncResult)asyncResult;
274 r.AsyncWaitHandle.WaitOne ();
276 if (r.ErrorCode != 0) {
278 r.VM.ErrorHandler (null, new ErrorHandlerEventArgs () { ErrorCode = r.ErrorCode });
279 } catch (CommandException ex) {
280 if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
281 throw new ArgumentException ("Incorrect number or types of arguments", "arguments");
285 throw new NotImplementedException ();
287 if (r.Exception != null)
288 throw new InvocationException ((ObjectMirror)r.VM.DecodeValue (r.Exception));
290 return r.VM.DecodeValue (r.Value);
294 internal static void EndInvokeMultipleInternal (IAsyncResult asyncResult) {
295 if (asyncResult == null)
296 throw new ArgumentNullException ("asyncResult");
298 InvokeAsyncResult r = (InvokeAsyncResult)asyncResult;
301 r.AsyncWaitHandle.WaitOne ();
304 internal static Value InvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, Value this_obj, IList<Value> arguments, InvokeOptions options) {
305 return EndInvokeMethodInternal (BeginInvokeMethod (vm, thread, method, this_obj, arguments, options, null, null));
308 internal static void AbortInvoke (VirtualMachine vm, ThreadMirror thread, int id)
310 vm.conn.VM_AbortInvoke (thread.Id, id);
314 // Implementation of InvokeMultiple
317 internal static IInvokeAsyncResult BeginInvokeMultiple (VirtualMachine vm, ThreadMirror thread, MethodMirror[] methods, Value this_obj, IList<IList<Value>> arguments, InvokeOptions options, AsyncCallback callback, object state) {
319 throw new ArgumentNullException ("thread");
321 throw new ArgumentNullException ("methods");
322 foreach (var m in methods)
324 throw new ArgumentNullException ("method");
325 if (arguments == null) {
326 arguments = new List<IList<Value>> ();
327 for (int i = 0; i < methods.Length; ++i)
328 arguments.Add (new Value [0]);
330 // FIXME: Not needed for property evaluation
331 throw new NotImplementedException ();
333 if (callback == null)
334 throw new ArgumentException ("A callback argument is required for this method.", "callback");
336 InvokeFlags f = InvokeFlags.NONE;
338 if ((options & InvokeOptions.DisableBreakpoints) != 0)
339 f |= InvokeFlags.DISABLE_BREAKPOINTS;
340 if ((options & InvokeOptions.SingleThreaded) != 0)
341 f |= InvokeFlags.SINGLE_THREADED;
343 InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback, NumPending = methods.Length, IsMultiple = true };
345 var mids = new long [methods.Length];
346 for (int i = 0; i < methods.Length; ++i)
347 mids [i] = methods [i].Id;
348 var args = new List<ValueImpl[]> ();
349 for (int i = 0; i < methods.Length; ++i)
350 args.Add (vm.EncodeValues (arguments [i]));
351 r.ID = vm.conn.VM_BeginInvokeMethods (thread.Id, mids, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), args, f, InvokeMultipleCB, r);
356 // This is called when the result of an invoke is received
357 static void InvokeMultipleCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) {
358 var r = (InvokeAsyncResult)state;
360 Interlocked.Decrement (ref r.NumPending);
362 if (r.NumPending == 0) {
363 r.IsCompleted = true;
364 ((ManualResetEvent)r.AsyncWaitHandle).Set ();
367 // Have to pass another asyncresult to the callback since multiple threads can execute it concurrently with results of multiple invocations
368 var r2 = new InvokeAsyncResult { AsyncState = r.AsyncState, AsyncWaitHandle = null, VM = r.VM, Thread = r.Thread, Callback = r.Callback, IsCompleted = true };
371 r2.ErrorCode = error;
377 r.Callback.BeginInvoke (r2, null, null);