3333using System . Collections . Generic ;
3434using System . Runtime . CompilerServices ;
3535using System . Threading ;
36-
36+ using System . Threading . Tasks ;
3737using Mono . Debugger . Soft ;
3838using Mono . Debugging . Backend ;
3939using Mono . Debugging . Evaluation ;
@@ -2177,30 +2177,36 @@ static string MirrorStringToString (EvaluationContext ctx, StringMirror mirror)
21772177 }
21782178 }
21792179
2180- class MethodCall : AsyncOperation
2180+ internal class SoftOperationResult : OperationResult < Value >
21812181 {
2182- readonly InvokeOptions options = InvokeOptions . DisableBreakpoints | InvokeOptions . SingleThreaded ;
2182+ public SoftOperationResult ( Value result , bool resultIsException , Value [ ] outArgs ) : base ( result , resultIsException )
2183+ {
2184+ OutArgs = outArgs ;
2185+ }
2186+
2187+ public Value [ ] OutArgs { get ; private set ; }
2188+ }
21832189
2184- readonly ManualResetEvent shutdownEvent = new ManualResetEvent ( false ) ;
2190+ internal class SoftMethodCall : AsyncOperationBase < Value >
2191+ {
2192+ readonly InvokeOptions options = InvokeOptions . DisableBreakpoints | InvokeOptions . SingleThreaded ;
21852193 readonly SoftEvaluationContext ctx ;
21862194 readonly MethodMirror function ;
21872195 readonly Value [ ] args ;
2188- readonly object obj ;
2189- IAsyncResult handle ;
2190- Exception exception ;
2191- IInvokeResult result ;
2192-
2193- public MethodCall ( SoftEvaluationContext ctx , MethodMirror function , object obj , Value [ ] args , bool enableOutArgs )
2196+ readonly IInvocableMethodOwnerMirror obj ;
2197+ IInvokeAsyncResult invokeAsyncResult ;
2198+
2199+ public SoftMethodCall ( SoftEvaluationContext ctx , MethodMirror function , IInvocableMethodOwnerMirror obj , Value [ ] args , bool enableOutArgs )
21942200 {
21952201 this . ctx = ctx ;
21962202 this . function = function ;
21972203 this . obj = obj ;
21982204 this . args = args ;
21992205 if ( enableOutArgs ) {
2200- this . options |= InvokeOptions . ReturnOutArgs ;
2206+ options |= InvokeOptions . ReturnOutArgs ;
22012207 }
22022208 if ( function . VirtualMachine . Version . AtLeast ( 2 , 40 ) ) {
2203- this . options |= InvokeOptions . Virtual ;
2209+ options |= InvokeOptions . Virtual ;
22042210 }
22052211 }
22062212
@@ -2210,113 +2216,60 @@ public override string Description {
22102216 }
22112217 }
22122218
2213- public override void Invoke ( )
2219+ protected override void AfterCancelledImpl ( int elapsedAfterCancelMs )
22142220 {
2215- try {
2216- var invocableMirror = obj as IInvocableMethodOwnerMirror ;
2217- if ( invocableMirror != null ) {
2218- var optionsToInvoke = options ;
2219- if ( obj is StructMirror ) {
2220- optionsToInvoke |= InvokeOptions . ReturnOutThis ;
2221- }
2222- handle = invocableMirror . BeginInvokeMethod ( ctx . Thread , function , args , optionsToInvoke , null , null ) ;
2223- }
2224- else
2225- throw new ArgumentException ( "Soft debugger method calls cannot be invoked on objects of type " + obj . GetType ( ) . Name ) ;
2226- } catch ( InvocationException ex ) {
2227- ctx . Session . StackVersion ++ ;
2228- exception = ex ;
2229- } catch ( Exception ex ) {
2230- ctx . Session . StackVersion ++ ;
2231- DebuggerLoggingService . LogError ( "Error in soft debugger method call thread on " + GetInfo ( ) , ex ) ;
2232- exception = ex ;
2233- }
22342221 }
22352222
2236- public override void Abort ( )
2237- {
2238- if ( handle is IInvokeAsyncResult ) {
2239- var info = GetInfo ( ) ;
2240- DebuggerLoggingService . LogMessage ( "Aborting invocation of " + info ) ;
2241- ( ( IInvokeAsyncResult ) handle ) . Abort ( ) ;
2242- // Don't wait for the abort to finish. The engine will do it.
2243- } else {
2244- throw new NotSupportedException ( ) ;
2245- }
2246- }
2247-
2248- public override void Shutdown ( )
2249- {
2250- shutdownEvent . Set ( ) ;
2251- }
2252-
2253- void EndInvoke ( )
2223+ protected override Task < OperationResult < Value > > InvokeAsyncImpl ( CancellationToken token )
22542224 {
22552225 try {
2256- result = ( ( IInvocableMethodOwnerMirror ) obj ) . EndInvokeMethodWithResult ( handle ) ;
2257- } catch ( InvocationException ex ) {
2258- if ( ! Aborting && ex . Exception != null ) {
2259- string ename = ctx . Adapter . GetValueTypeName ( ctx , ex . Exception ) ;
2260- var vref = ctx . Adapter . GetMember ( ctx , null , ex . Exception , "Message" ) ;
2261-
2262- exception = vref != null ? new Exception ( ename + ": " + ( string ) vref . ObjectValue ) : new Exception ( ename ) ;
2263- return ;
2226+ var optionsToInvoke = options ;
2227+ if ( obj is StructMirror ) {
2228+ optionsToInvoke |= InvokeOptions . ReturnOutThis ;
22642229 }
2265- exception = ex ;
2266- } catch ( Exception ex ) {
2267- DebuggerLoggingService . LogError ( "Error in soft debugger method call thread on " + GetInfo ( ) , ex ) ;
2268- exception = ex ;
2269- } finally {
2270- ctx . Session . StackVersion ++ ;
2271- }
2272- }
2273-
2274- string GetInfo ( )
2275- {
2276- try {
2277- TypeMirror type = null ;
2278- if ( obj is ObjectMirror )
2279- type = ( ( ObjectMirror ) obj ) . Type ;
2280- else if ( obj is TypeMirror )
2281- type = ( TypeMirror ) obj ;
2282- else if ( obj is StructMirror )
2283- type = ( ( StructMirror ) obj ) . Type ;
2284- return string . Format ( "method {0} on object {1}" ,
2285- function == null ? "[null]" : function . FullName ,
2286- type == null ? "[null]" : type . FullName ) ;
2287- } catch ( Exception ex ) {
2288- DebuggerLoggingService . LogError ( "Error getting info for SDB MethodCall" , ex ) ;
2289- return "" ;
2230+ var tcs = new TaskCompletionSource < OperationResult < Value > > ( ) ;
2231+ invokeAsyncResult = ( IInvokeAsyncResult ) obj . BeginInvokeMethod ( ctx . Thread , function , args , optionsToInvoke , ar => {
2232+ try {
2233+ var endInvokeResult = obj . EndInvokeMethodWithResult ( ar ) ;
2234+ token . ThrowIfCancellationRequested ( ) ;
2235+ tcs . SetResult ( new SoftOperationResult ( endInvokeResult . Result , false , endInvokeResult . OutArgs ) ) ;
2236+ }
2237+ catch ( InvocationException ex ) {
2238+ // throw OCE if cancelled
2239+ token . ThrowIfCancellationRequested ( ) ;
2240+ if ( ex . Exception != null ) {
2241+ tcs . SetResult ( new SoftOperationResult ( ex . Exception , true , null ) ) ;
2242+ }
2243+ else {
2244+ tcs . SetException ( new EvaluatorException ( "Target method has thrown an exception but the exception object is inaccessible" ) ) ;
2245+ }
2246+ }
2247+ catch ( Exception e ) {
2248+ tcs . SetException ( e ) ;
2249+ }
2250+ finally {
2251+ UpdateSessionState ( ) ;
2252+ }
2253+ } , null ) ;
2254+ return tcs . Task ;
2255+ } catch ( Exception ) {
2256+ UpdateSessionState ( ) ;
2257+ throw ;
22902258 }
22912259 }
22922260
2293- public override bool WaitForCompleted ( int timeout )
2261+ void UpdateSessionState ( )
22942262 {
2295- if ( handle == null )
2296- return true ;
2297- int res = WaitHandle . WaitAny ( new WaitHandle [ ] { handle . AsyncWaitHandle , shutdownEvent } , timeout ) ;
2298- if ( res == 0 ) {
2299- EndInvoke ( ) ;
2300- return true ;
2301- }
2302- // Return true if shut down.
2303- return res == 1 ;
2263+ ctx . Session . StackVersion ++ ;
23042264 }
23052265
2306- public Value ReturnValue {
2307- get {
2308- if ( exception != null )
2309- throw new EvaluatorException ( exception . Message ) ;
2310- return result . Result ;
2311- }
2312- }
2313-
2314- public Value [ ] OutArgs {
2315- get {
2316- if ( exception != null )
2317- throw new EvaluatorException ( exception . Message ) ;
2318- return result . OutArgs ;
2266+ protected override void CancelImpl ( )
2267+ {
2268+ if ( invokeAsyncResult == null ) {
2269+ DebuggerLoggingService . LogError ( "invokeAsyncResult is null" , new ArgumentNullException ( "invokeAsyncResult" ) ) ;
2270+ return ;
23192271 }
2272+ invokeAsyncResult . Abort ( ) ;
23202273 }
23212274 }
23222275}
0 commit comments