3333using System . Collections . Generic ;
3434using System . Runtime . CompilerServices ;
3535using System . Threading ;
36-
36+ using System . Threading . Tasks ;
3737using Mono . Debugger . Soft ;
3838using Mono . Debugging . Evaluation ;
3939using Mono . Debugging . Client ;
@@ -2166,30 +2166,36 @@ static string MirrorStringToString (EvaluationContext ctx, StringMirror mirror)
21662166 }
21672167 }
21682168
2169- class MethodCall : AsyncOperation
2169+ internal class SoftOperationResult : OperationResult < Value >
21702170 {
2171- readonly InvokeOptions options = InvokeOptions . DisableBreakpoints | InvokeOptions . SingleThreaded ;
2171+ public SoftOperationResult ( Value result , bool resultIsException , Value [ ] outArgs ) : base ( result , resultIsException )
2172+ {
2173+ OutArgs = outArgs ;
2174+ }
2175+
2176+ public Value [ ] OutArgs { get ; private set ; }
2177+ }
21722178
2173- readonly ManualResetEvent shutdownEvent = new ManualResetEvent ( false ) ;
2179+ internal class SoftMethodCall : AsyncOperationBase < Value >
2180+ {
2181+ readonly InvokeOptions options = InvokeOptions . DisableBreakpoints | InvokeOptions . SingleThreaded ;
21742182 readonly SoftEvaluationContext ctx ;
21752183 readonly MethodMirror function ;
21762184 readonly Value [ ] args ;
2177- readonly object obj ;
2178- IAsyncResult handle ;
2179- Exception exception ;
2180- IInvokeResult result ;
2181-
2182- public MethodCall ( SoftEvaluationContext ctx , MethodMirror function , object obj , Value [ ] args , bool enableOutArgs )
2185+ readonly IInvocableMethodOwnerMirror obj ;
2186+ IInvokeAsyncResult invokeAsyncResult ;
2187+
2188+ public SoftMethodCall ( SoftEvaluationContext ctx , MethodMirror function , IInvocableMethodOwnerMirror obj , Value [ ] args , bool enableOutArgs )
21832189 {
21842190 this . ctx = ctx ;
21852191 this . function = function ;
21862192 this . obj = obj ;
21872193 this . args = args ;
21882194 if ( enableOutArgs ) {
2189- this . options |= InvokeOptions . ReturnOutArgs ;
2195+ options |= InvokeOptions . ReturnOutArgs ;
21902196 }
21912197 if ( function . VirtualMachine . Version . AtLeast ( 2 , 40 ) ) {
2192- this . options |= InvokeOptions . Virtual ;
2198+ options |= InvokeOptions . Virtual ;
21932199 }
21942200 }
21952201
@@ -2199,113 +2205,60 @@ public override string Description {
21992205 }
22002206 }
22012207
2202- public override void Invoke ( )
2208+ protected override void AfterCancelledImpl ( int elapsedAfterCancelMs )
22032209 {
2204- try {
2205- var invocableMirror = obj as IInvocableMethodOwnerMirror ;
2206- if ( invocableMirror != null ) {
2207- var optionsToInvoke = options ;
2208- if ( obj is StructMirror ) {
2209- optionsToInvoke |= InvokeOptions . ReturnOutThis ;
2210- }
2211- handle = invocableMirror . BeginInvokeMethod ( ctx . Thread , function , args , optionsToInvoke , null , null ) ;
2212- }
2213- else
2214- throw new ArgumentException ( "Soft debugger method calls cannot be invoked on objects of type " + obj . GetType ( ) . Name ) ;
2215- } catch ( InvocationException ex ) {
2216- ctx . Session . StackVersion ++ ;
2217- exception = ex ;
2218- } catch ( Exception ex ) {
2219- ctx . Session . StackVersion ++ ;
2220- DebuggerLoggingService . LogError ( "Error in soft debugger method call thread on " + GetInfo ( ) , ex ) ;
2221- exception = ex ;
2222- }
22232210 }
22242211
2225- public override void Abort ( )
2226- {
2227- if ( handle is IInvokeAsyncResult ) {
2228- var info = GetInfo ( ) ;
2229- DebuggerLoggingService . LogMessage ( "Aborting invocation of " + info ) ;
2230- ( ( IInvokeAsyncResult ) handle ) . Abort ( ) ;
2231- // Don't wait for the abort to finish. The engine will do it.
2232- } else {
2233- throw new NotSupportedException ( ) ;
2234- }
2235- }
2236-
2237- public override void Shutdown ( )
2238- {
2239- shutdownEvent . Set ( ) ;
2240- }
2241-
2242- void EndInvoke ( )
2212+ protected override Task < OperationResult < Value > > InvokeAsyncImpl ( CancellationToken token )
22432213 {
22442214 try {
2245- result = ( ( IInvocableMethodOwnerMirror ) obj ) . EndInvokeMethodWithResult ( handle ) ;
2246- } catch ( InvocationException ex ) {
2247- if ( ! Aborting && ex . Exception != null ) {
2248- string ename = ctx . Adapter . GetValueTypeName ( ctx , ex . Exception ) ;
2249- var vref = ctx . Adapter . GetMember ( ctx , null , ex . Exception , "Message" ) ;
2250-
2251- exception = vref != null ? new Exception ( ename + ": " + ( string ) vref . ObjectValue ) : new Exception ( ename ) ;
2252- return ;
2215+ var optionsToInvoke = options ;
2216+ if ( obj is StructMirror ) {
2217+ optionsToInvoke |= InvokeOptions . ReturnOutThis ;
22532218 }
2254- exception = ex ;
2255- } catch ( Exception ex ) {
2256- DebuggerLoggingService . LogError ( "Error in soft debugger method call thread on " + GetInfo ( ) , ex ) ;
2257- exception = ex ;
2258- } finally {
2259- ctx . Session . StackVersion ++ ;
2260- }
2261- }
2262-
2263- string GetInfo ( )
2264- {
2265- try {
2266- TypeMirror type = null ;
2267- if ( obj is ObjectMirror )
2268- type = ( ( ObjectMirror ) obj ) . Type ;
2269- else if ( obj is TypeMirror )
2270- type = ( TypeMirror ) obj ;
2271- else if ( obj is StructMirror )
2272- type = ( ( StructMirror ) obj ) . Type ;
2273- return string . Format ( "method {0} on object {1}" ,
2274- function == null ? "[null]" : function . FullName ,
2275- type == null ? "[null]" : type . FullName ) ;
2276- } catch ( Exception ex ) {
2277- DebuggerLoggingService . LogError ( "Error getting info for SDB MethodCall" , ex ) ;
2278- return "" ;
2219+ var tcs = new TaskCompletionSource < OperationResult < Value > > ( ) ;
2220+ invokeAsyncResult = ( IInvokeAsyncResult ) obj . BeginInvokeMethod ( ctx . Thread , function , args , optionsToInvoke , ar => {
2221+ try {
2222+ var endInvokeResult = obj . EndInvokeMethodWithResult ( ar ) ;
2223+ token . ThrowIfCancellationRequested ( ) ;
2224+ tcs . SetResult ( new SoftOperationResult ( endInvokeResult . Result , false , endInvokeResult . OutArgs ) ) ;
2225+ }
2226+ catch ( InvocationException ex ) {
2227+ // throw OCE if cancelled
2228+ token . ThrowIfCancellationRequested ( ) ;
2229+ if ( ex . Exception != null ) {
2230+ tcs . SetResult ( new SoftOperationResult ( ex . Exception , true , null ) ) ;
2231+ }
2232+ else {
2233+ tcs . SetException ( new EvaluatorException ( "Target method has thrown an exception but the exception object is inaccessible" ) ) ;
2234+ }
2235+ }
2236+ catch ( Exception e ) {
2237+ tcs . SetException ( e ) ;
2238+ }
2239+ finally {
2240+ UpdateSessionState ( ) ;
2241+ }
2242+ } , null ) ;
2243+ return tcs . Task ;
2244+ } catch ( Exception ) {
2245+ UpdateSessionState ( ) ;
2246+ throw ;
22792247 }
22802248 }
22812249
2282- public override bool WaitForCompleted ( int timeout )
2250+ void UpdateSessionState ( )
22832251 {
2284- if ( handle == null )
2285- return true ;
2286- int res = WaitHandle . WaitAny ( new WaitHandle [ ] { handle . AsyncWaitHandle , shutdownEvent } , timeout ) ;
2287- if ( res == 0 ) {
2288- EndInvoke ( ) ;
2289- return true ;
2290- }
2291- // Return true if shut down.
2292- return res == 1 ;
2252+ ctx . Session . StackVersion ++ ;
22932253 }
22942254
2295- public Value ReturnValue {
2296- get {
2297- if ( exception != null )
2298- throw new EvaluatorException ( exception . Message ) ;
2299- return result . Result ;
2300- }
2301- }
2302-
2303- public Value [ ] OutArgs {
2304- get {
2305- if ( exception != null )
2306- throw new EvaluatorException ( exception . Message ) ;
2307- return result . OutArgs ;
2255+ protected override void CancelImpl ( )
2256+ {
2257+ if ( invokeAsyncResult == null ) {
2258+ DebuggerLoggingService . LogError ( "invokeAsyncResult is null" , new ArgumentNullException ( "invokeAsyncResult" ) ) ;
2259+ return ;
23082260 }
2261+ invokeAsyncResult . Abort ( ) ;
23092262 }
23102263 }
23112264}
0 commit comments