void IThreadPoolWorkItem.ExecuteWorkItem()
{
- async_result.Invoke ();
+ ((IThreadPoolWorkItem) async_result).ExecuteWorkItem ();
}
void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
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);
using System;
using System.Threading;
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
WaitHandle handle;
object async_delegate;
IntPtr data;
- object object_data;
+ MonoAsyncCall async_call;
bool sync_completed;
bool completed;
bool endinvoke_called;
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 ();
}
}
}
return outCount > 0 || res;
}
-
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern object Invoke (object target, out object[] out_args);
}
internal enum CallType: int
* 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)]
//
// 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
* 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
{
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)
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);
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;
} 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;
/* 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);
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,
*
*/
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);
}
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));
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,
#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)) {
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;
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))
}
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);
*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