Merge pull request #1912 from ludovic-henry/threadpool-managed-asyncresult
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 3 Aug 2015 21:37:54 +0000 (17:37 -0400)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 3 Aug 2015 21:37:54 +0000 (17:37 -0400)
[runtime] Move AsyncResult.Invoke to managed

12 files changed:
mcs/class/System/System.Diagnostics/Process.cs
mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs
mcs/class/corlib/System.Runtime.Remoting.Messaging/AsyncResult.cs
mcs/class/corlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.cs
mcs/class/corlib/System/Environment.cs
mcs/class/corlib/System/MonoAsyncCall.cs
mono/metadata/appdomain.c
mono/metadata/icall-def.h
mono/metadata/marshal.c
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/threadpool-ms.c

index a7c793bedbfc678d40db6f923a06a29f850939b6..dc2614c674976643cc4695ecece34031cc941c3f 100644 (file)
@@ -1496,7 +1496,7 @@ namespace System.Diagnostics {
 
                        void IThreadPoolWorkItem.ExecuteWorkItem()
                        {
-                               async_result.Invoke ();
+                               ((IThreadPoolWorkItem) async_result).ExecuteWorkItem ();
                        }
 
                        void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
index f1cd229d865c13fa15a81e734373d105dad93438..467cafa139a057ac5efad1bb01863e894a837aa6 100644 (file)
@@ -304,7 +304,7 @@ namespace System.Net.Sockets
 
                void IThreadPoolWorkItem.ExecuteWorkItem()
                {
-                       async_result.Invoke ();
+                       ((IThreadPoolWorkItem) async_result).ExecuteWorkItem ();
 
                        if (completed && callback != null) {
                                ThreadPool.UnsafeQueueCustomWorkItem (new AsyncResult (state => callback ((IAsyncResult) state), this, false), false);
index ff43f8dc0d0301c6df76aaf30b3e6e175dcdb352..bf696a37c291ed5b6e9f6e34ef6895b8af2f8b99 100644 (file)
@@ -32,6 +32,7 @@
 
 using System;
 using System.Threading;
+using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
@@ -46,7 +47,7 @@ public class AsyncResult : IAsyncResult, IMessageSink, IThreadPoolWorkItem {
        WaitHandle handle;
        object async_delegate;
        IntPtr data;
-       object object_data;
+       MonoAsyncCall async_call;
        bool sync_completed;
        bool completed;
        bool endinvoke_called;
@@ -207,14 +208,29 @@ public class AsyncResult : IAsyncResult, IMessageSink, IThreadPoolWorkItem {
 
        void IThreadPoolWorkItem.ExecuteWorkItem()
        {
-               Invoke ();
+               if (async_call == null) {
+                       ((WaitCallback) async_delegate) (async_state);
+               } else {
+                       try {
+                               async_call.result = async_call.message.Invoke (async_delegate, out async_call.out_args);
+                               async_call.message.exc = null;
+                       } catch (Exception e) {
+                               async_call.message.exc = e;
+                       }
+
+                       lock (this) {
+                               completed = true;
+                               if (handle != null)
+                                       ((ManualResetEvent) handle).Set ();
+                       }
+
+                       if (async_call.callback != null)
+                               async_call.callback (this);
+               }
        }
 
        void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
        {
        }
-
-       [MethodImplAttribute(MethodImplOptions.InternalCall)]
-       internal extern object Invoke ();
 }
 }
index 3b324d1eab7076389642e0a1776b0343f9366ada..f366e7fcbdebc54f47fbb146e5ec9347039fc1fa 100644 (file)
@@ -371,7 +371,9 @@ namespace System.Runtime.Remoting.Messaging {
                        }
                        return outCount > 0 || res;
                }
-               
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern object Invoke (object target, out object[] out_args);
        }
 
        internal enum CallType: int
index c6b01d789c92fb67ef1b4e0e4a7bcdd8d000caa1..81cad6caa28da0b0d63223001a93013b2d172e48 100644 (file)
@@ -57,7 +57,7 @@ namespace System {
                 * of icalls, do not require an increment.
                 */
 #pragma warning disable 169
-               private const int mono_corlib_version = 135;
+               private const int mono_corlib_version = 136;
 #pragma warning restore 169
 
                [ComVisible (true)]
index e6944a1bc4d7f41dd6b9a6e5a7d94bcd6db94506..d996c0a8b31c474165af91c40d9f16f6839e5bad 100644 (file)
@@ -3,7 +3,7 @@
 //
 // Author:
 //    Zoltan Varga (vargaz@gmail.com)
-//
+//    Ludovic Henry (ludovic@xamarin.com)
 //
 
 //
 //
 
 //
-// This is the managed counterpart of the ASyncCall structure used by the threadpools.
+// This is the managed counterpart of the MonoAsyncCall structure used by the threadpools.
 //
 using System.Runtime.InteropServices;
+using System.Runtime.Remoting.Messaging;
 
 namespace System {
 
 #pragma warning disable 169
 
        [StructLayout (LayoutKind.Sequential)]
-       internal class MonoAsyncCall {
-               #region Sync with the unmanaged ASyncCall structure
-               object     msg;
-               IntPtr     cb_method;
-               object     cb_target;
-               object     state;
-               object     res;
-               object     out_args;
-               #endregion
+       internal class MonoAsyncCall
+       {
+               /*
+                * Keep in sync with runtime structure MonoAsyncCall
+                */
+
+               internal MonoMethodMessage message;
+
+               internal AsyncCallback callback;
+
+               internal object state;
+
+               internal object result;
+
+               internal object[] out_args;
        }
 
 #pragma warning restore 169    
index 2bfa5457e77c5b14d7f26180aa765d9d529840d5..4685be776726472106bc0df39fa0f0b630fd8318 100644 (file)
@@ -79,7 +79,7 @@
  * Changes which are already detected at runtime, like the addition
  * of icalls, do not require an increment.
  */
-#define MONO_CORLIB_VERSION 135
+#define MONO_CORLIB_VERSION 136
 
 typedef struct
 {
index 677769c97e54d7930a40f7071b20d2b16412ae1d..3187a6b3876e2c4d0e04660f282cc095727b1b90 100644 (file)
@@ -705,11 +705,9 @@ ICALL_TYPE(CONTEXT, "System.Runtime.Remoting.Contexts.Context", CONTEXT_1)
 ICALL(CONTEXT_1, "RegisterContext", ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext)
 ICALL(CONTEXT_2, "ReleaseContext", ves_icall_System_Runtime_Remoting_Contexts_Context_ReleaseContext)
 
-ICALL_TYPE(ARES, "System.Runtime.Remoting.Messaging.AsyncResult", ARES_1)
-ICALL(ARES_1, "Invoke", ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke)
-
 ICALL_TYPE(MONOMM, "System.Runtime.Remoting.Messaging.MonoMethodMessage", MONOMM_1)
 ICALL(MONOMM_1, "InitMessage", ves_icall_MonoMethodMessage_InitMessage)
+ICALL(MONOMM_2, "Invoke", ves_icall_System_Runtime_Remoting_Messaging_MonoMethodMessage_Invoke)
 
 #ifndef DISABLE_REMOTING
 ICALL_TYPE(REALP, "System.Runtime.Remoting.Proxies.RealProxy", REALP_1)
index f31f17c46862ae1b1e649ab4ffa65167d1bf5ce9..b58eb166012b97a43a949d293728b2c2e33e761d 100644 (file)
@@ -2074,7 +2074,7 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
                        method = delegate->method;
 
                        msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state);
-                       ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL, NULL);
+                       ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL);
                        MONO_OBJECT_SETREF (ares, async_delegate, (MonoObject *)delegate);
                        MONO_OBJECT_SETREF (ares, async_callback, (MonoObject *)async_callback);
                        MONO_OBJECT_SETREF (msg, async_result, ares);
index 027d3e1b8a675b4d07ae1c5967789ffe0827ba0d..e07acc2bedd05f2b37d695c936ce922b2ef51955 100644 (file)
@@ -266,13 +266,15 @@ typedef struct {
        MonoString *param_name;
 } MonoArgumentException;
 
+typedef struct _MonoAsyncCall MonoAsyncCall;
+
 typedef struct {
        MonoObject   object;
        MonoObject  *async_state;
        MonoObject  *handle;
        MonoObject  *async_delegate;
        gpointer    *data;
-       MonoObject  *object_data;
+       MonoAsyncCall  *async_call;
        MonoBoolean  sync_completed;
        MonoBoolean  completed;
        MonoBoolean  endinvoke_called;
@@ -353,15 +355,14 @@ typedef struct {
 } MonoMethodMessage;
 
 /* Keep in sync with the System.MonoAsyncCall */
-typedef struct {
+struct _MonoAsyncCall {
        MonoObject object;
        MonoMethodMessage *msg;
-       MonoMethod *cb_method;
-       MonoDelegate *cb_target;
+       MonoDelegate *callback;
        MonoObject *state;
        MonoObject *res;
        MonoArray *out_args;
-} MonoAsyncCall;
+};
 
 typedef struct {
        MonoObject obj;
@@ -630,14 +631,7 @@ MONO_COLD void mono_set_pending_exception (MonoException *exc);
 /* remoting and async support */
 
 MonoAsyncResult *
-mono_async_result_new      (MonoDomain *domain, HANDLE handle, 
-                            MonoObject *state, gpointer data, MonoObject *object_data);
-
-MonoObject *
-mono_async_result_invoke    (MonoAsyncResult *ares, MonoObject **exc);
-
-MonoObject *
-ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *this_obj);
+mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data);
 
 MonoWaitHandle *
 mono_wait_handle_new       (MonoDomain *domain, HANDLE handle);
@@ -650,8 +644,8 @@ mono_message_init       (MonoDomain *domain, MonoMethodMessage *this_obj,
                             MonoReflectionMethod *method, MonoArray *out_args);
 
 MonoObject *
-mono_message_invoke        (MonoObject *target, MonoMethodMessage *msg, 
-                            MonoObject **exc, MonoArray **out_args);
+ves_icall_System_Runtime_Remoting_Messaging_MonoMethodMessage_Invoke (MonoMethodMessage *this,
+               MonoObject *target, MonoArray **out_args);
 
 MonoMethodMessage *
 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke, 
index cd6ff901063e92fd6ee262e6069c861c5d14094c..4640730aec1ba8b49cd7185f2ac5c30bd3501566 100644 (file)
@@ -5760,7 +5760,7 @@ mono_runtime_capture_context (MonoDomain *domain)
  *
  */
 MonoAsyncResult *
-mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
+mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
 {
        MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
        MonoObject *context = mono_runtime_capture_context (domain);
@@ -5771,7 +5771,6 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
        }
 
        res->data = data;
-       MONO_OBJECT_SETREF (res, object_data, object_data);
        MONO_OBJECT_SETREF (res, async_state, state);
        if (handle != NULL)
                MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
@@ -5782,60 +5781,6 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
        return res;
 }
 
-MonoObject *
-mono_async_result_invoke (MonoAsyncResult *ares, MonoObject **exc)
-{
-       MonoAsyncCall *ac;
-       MonoObject *res;
-       MonoInternalThread *thread;
-
-       g_assert (ares);
-       g_assert (ares->async_delegate);
-
-       thread = mono_thread_internal_current ();
-
-       ac = (MonoAsyncCall*) ares->object_data;
-       if (!ac) {
-               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, exc);
-       } else {
-               MonoArray *out_args = NULL;
-               gpointer wait_event = NULL;
-
-               ac->msg->exc = NULL;
-               res = mono_message_invoke (ares->async_delegate, ac->msg, exc, &out_args);
-               MONO_OBJECT_SETREF (ac->msg, exc, *exc);
-               MONO_OBJECT_SETREF (ac, res, res);
-               MONO_OBJECT_SETREF (ac, out_args, out_args);
-
-               mono_monitor_enter ((MonoObject*) ares);
-               ares->completed = 1;
-               if (ares->handle)
-                       wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle);
-               mono_monitor_exit ((MonoObject*) ares);
-
-               if (wait_event != NULL)
-                       SetEvent (wait_event);
-
-               if (!ac->cb_method) {
-                       *exc = NULL;
-               } else {
-                       mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, exc);
-               }
-       }
-
-       return res;
-}
-
-MonoObject *
-ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *this_obj)
-{
-       MonoObject *exc = NULL;
-       MonoObject *res = mono_async_result_invoke (this_obj, &exc);
-       if (exc)
-               mono_raise_exception ((MonoException*) exc);
-       return res;
-}
-
 void
 mono_message_init (MonoDomain *domain,
                   MonoMethodMessage *this_obj, 
@@ -5944,15 +5889,14 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
 #endif
 
 MonoObject *
-mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, 
-                    MonoObject **exc, MonoArray **out_args) 
+ves_icall_System_Runtime_Remoting_Messaging_MonoMethodMessage_Invoke (MonoMethodMessage *this,
+               MonoObject *target, MonoArray **out_args)
 {
-       static MonoClass *object_array_klass;
-       MonoDomain *domain; 
+       static MonoClass *object_array_klass = NULL;
        MonoMethod *method;
        MonoMethodSignature *sig;
        MonoObject *ret;
-       int i, j, outarg_count = 0;
+       int i, j, out_args_count = 0;
 
 #ifndef DISABLE_REMOTING
        if (target && mono_object_is_transparent_proxy (target)) {
@@ -5960,43 +5904,40 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
                if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
                        target = tp->rp->unwrapped_server;
                } else {
-                       return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
+                       MonoObject *exc = NULL;
+                       MonoObject *ret = mono_remoting_invoke ((MonoObject *)tp->rp, this, &exc, out_args);
+                       if (exc)
+                               mono_raise_exception (exc);
+                       return ret;
                }
        }
 #endif
 
-       domain = mono_domain_get (); 
-       method = msg->method->method;
-       sig = mono_method_signature (method);
+       g_assert (out_args);
 
-       for (i = 0; i < sig->param_count; i++) {
-               if (sig->params [i]->byref) 
-                       outarg_count++;
-       }
+       if (!object_array_klass)
+               object_array_klass = mono_array_class_get (mono_defaults.object_class, 1);
+       g_assert (object_array_klass);
 
-       if (!object_array_klass) {
-               MonoClass *klass;
+       method = this->method->method;
 
-               klass = mono_array_class_get (mono_defaults.object_class, 1);
-               g_assert (klass);
+       if (method->klass->valuetype)
+               ret = mono_runtime_invoke_array (method, mono_object_unbox (target), this->args, NULL);
+       else
+               ret = mono_runtime_invoke_array (method, target, this->args, NULL);
 
-               mono_memory_barrier ();
-               object_array_klass = klass;
-       }
+       sig = mono_method_signature (method);
 
-       /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
-       *out_args = mono_array_new_specific (mono_class_vtable (domain, object_array_klass), outarg_count);
-       *exc = NULL;
+       for (i = 0; i < sig->param_count; i++) {
+               if (sig->params [i]->byref)
+                       out_args_count++;
+       }
 
-       ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
+       mono_gc_wbarrier_generic_store (out_args, (MonoObject*) mono_array_new_specific (mono_class_vtable (mono_domain_get (), object_array_klass), out_args_count));
 
        for (i = 0, j = 0; i < sig->param_count; i++) {
-               if (sig->params [i]->byref) {
-                       MonoObject* arg;
-                       arg = mono_array_get (msg->args, gpointer, i);
-                       mono_array_setref (*out_args, j, arg);
-                       j++;
-               }
+               if (sig->params [i]->byref)
+                       mono_array_setref (*out_args, j++, mono_array_get (this->args, gpointer, i));
        }
 
        return ret;
index 26ed2a1331958e33cbafd2a5e3cfc2e3cd654801..139f53910e485e989434408395ef0108ca9109a5 100644 (file)
@@ -1260,19 +1260,21 @@ mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMet
 
        mono_lazy_initialize (&status, initialize);
 
-       message = mono_method_call_message_new (method, params, mono_get_delegate_invoke (method->klass), (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL);
+       if (params)
+               message = mono_method_call_message_new (method, params, mono_get_delegate_invoke (method->klass), &async_callback, &state);
+       else
+               message = mono_method_call_message_new (method, params, mono_get_delegate_invoke (method->klass), NULL, NULL);
 
        async_call = (MonoAsyncCall*) mono_object_new (domain, async_call_klass);
        MONO_OBJECT_SETREF (async_call, msg, message);
        MONO_OBJECT_SETREF (async_call, state, state);
 
-       if (async_callback) {
-               MONO_OBJECT_SETREF (async_call, cb_method, mono_get_delegate_invoke (((MonoObject*) async_callback)->vtable->klass));
-               MONO_OBJECT_SETREF (async_call, cb_target, async_callback);
-       }
+       if (async_callback)
+               MONO_OBJECT_SETREF (async_call, callback, async_callback);
 
-       async_result = mono_async_result_new (domain, NULL, async_call->state, NULL, (MonoObject*) async_call);
+       async_result = mono_async_result_new (domain, NULL, async_call->state, NULL);
        MONO_OBJECT_SETREF (async_result, async_delegate, target);
+       MONO_OBJECT_SETREF (async_result, async_call, async_call);
 
 #ifndef DISABLE_SOCKETS
        if (mono_threadpool_ms_is_io (target, state))
@@ -1285,9 +1287,9 @@ mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMet
 }
 
 MonoObject *
-mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, MonoObject **exc)
+mono_threadpool_ms_end_invoke (MonoAsyncResult *async_result, MonoArray **out_args, MonoObject **exc)
 {
-       MonoAsyncCall *ac;
+       MonoAsyncCall *async_call;
 
        g_assert (exc);
        g_assert (out_args);
@@ -1296,40 +1298,40 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
        *out_args = NULL;
 
        /* check if already finished */
-       mono_monitor_enter ((MonoObject*) ares);
+       mono_monitor_enter ((MonoObject*) async_result);
 
-       if (ares->endinvoke_called) {
+       if (async_result->endinvoke_called) {
                *exc = (MonoObject*) mono_get_exception_invalid_operation (NULL);
-               mono_monitor_exit ((MonoObject*) ares);
+               mono_monitor_exit ((MonoObject*) async_result);
                return NULL;
        }
 
-       MONO_OBJECT_SETREF (ares, endinvoke_called, 1);
+       MONO_OBJECT_SETREF (async_result, endinvoke_called, 1);
 
        /* wait until we are really finished */
-       if (ares->completed) {
-               mono_monitor_exit ((MonoObject *) ares);
+       if (async_result->completed) {
+               mono_monitor_exit ((MonoObject *) async_result);
        } else {
                gpointer wait_event;
-               if (ares->handle) {
-                       wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle);
+               if (async_result->handle) {
+                       wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) async_result->handle);
                } else {
                        wait_event = CreateEvent (NULL, TRUE, FALSE, NULL);
                        g_assert(wait_event);
-                       MONO_OBJECT_SETREF (ares, handle, (MonoObject*) mono_wait_handle_new (mono_object_domain (ares), wait_event));
+                       MONO_OBJECT_SETREF (async_result, handle, (MonoObject*) mono_wait_handle_new (mono_object_domain (async_result), wait_event));
                }
-               mono_monitor_exit ((MonoObject*) ares);
+               mono_monitor_exit ((MonoObject*) async_result);
                MONO_PREPARE_BLOCKING;
                WaitForSingleObjectEx (wait_event, INFINITE, TRUE);
                MONO_FINISH_BLOCKING;
        }
 
-       ac = (MonoAsyncCall*) ares->object_data;
-       g_assert (ac);
+       async_call = async_result->async_call;
+       g_assert (async_call);
+       *exc = async_call->msg->exc; /* FIXME: GC add write barrier */
+       *out_args = async_call->out_args;
 
-       *exc = ac->msg->exc; /* FIXME: GC add write barrier */
-       *out_args = ac->out_args;
-       return ac->res;
+       return async_call->res;
 }
 
 gboolean