942 |
} |
} |
943 |
} |
} |
944 |
|
|
945 |
|
typedef struct { |
946 |
|
ILExecThread *thread; |
947 |
|
ffi_cif *cif; |
948 |
|
void *result; |
949 |
|
void **args; |
950 |
|
System_Delegate *delegate; |
951 |
|
} ILDelegateInvokeParams; |
952 |
|
|
953 |
/* |
/* |
954 |
* Invoke a delegate from a closure. |
* Do the real delegate invokation. |
955 |
*/ |
*/ |
956 |
static void DelegateInvoke(ffi_cif *cif, void *result, |
static void _DelegateInvoke(ILDelegateInvokeParams *params) |
|
void **args, void *delegate) |
|
957 |
{ |
{ |
|
ILExecThread *thread = ILExecThreadCurrent(); |
|
958 |
ILMethod *method; |
ILMethod *method; |
959 |
ILType *type; |
ILType *type; |
960 |
ILUInt32 size; |
ILUInt32 size; |
961 |
PackDelegateUserData userData; |
PackDelegateUserData userData; |
962 |
|
|
963 |
/* If this is a multicast delegate, then execute "prev" first */ |
/* If this is a multicast delegate, then execute "prev" first */ |
964 |
if(((System_Delegate *)delegate)->prev) |
if(params->delegate->prev) |
965 |
{ |
{ |
966 |
DelegateInvoke(cif, result, args, |
ILDelegateInvokeParams prevParams; |
967 |
((System_Delegate *)delegate)->prev); |
|
968 |
if(ILExecThreadHasException(thread)) |
prevParams.thread = params->thread; |
969 |
|
prevParams.cif = params->cif; |
970 |
|
prevParams.result = params->result; |
971 |
|
prevParams.args = params->args; |
972 |
|
prevParams.delegate = (System_Delegate *)(params->delegate->prev); |
973 |
|
; |
974 |
|
_DelegateInvoke(&prevParams); |
975 |
|
if(ILExecThreadHasException(params->thread)) |
976 |
{ |
{ |
977 |
return; |
return; |
978 |
} |
} |
979 |
} |
} |
980 |
|
|
981 |
/* Extract the method from the delegate */ |
/* Extract the method from the delegate */ |
982 |
method = ((System_Delegate *)delegate)->methodInfo; |
method = params->delegate->methodInfo; |
983 |
if(!method) |
if(!method) |
984 |
{ |
{ |
985 |
ILExecThreadThrowSystem(thread, "System.MissingMethodException", |
ILExecThreadThrowSystem(params->thread, "System.MissingMethodException", |
986 |
(const char *)0); |
(const char *)0); |
987 |
return; |
return; |
988 |
} |
} |
989 |
|
|
990 |
/* Call the method */ |
/* Call the method */ |
991 |
userData.args = args; |
userData.args = params->args; |
992 |
userData.pinvokeInfo = (ILMethod *)ILTypeGetDelegateMethod |
userData.pinvokeInfo = (ILMethod *)ILTypeGetDelegateMethod |
993 |
(ILType_FromClass(GetObjectClass(delegate))); |
(ILType_FromClass(GetObjectClass(params->delegate))); |
994 |
userData.needThis = 0; |
userData.needThis = 0; |
995 |
if(_ILCallMethod(thread, method, |
if(_ILCallMethod(params->thread, method, |
996 |
UnpackDelegateResult, result, |
UnpackDelegateResult, params->result, |
997 |
0, ((System_Delegate *)delegate)->target, |
0, params->delegate->target, |
998 |
PackDelegateParams, &userData)) |
PackDelegateParams, &userData)) |
999 |
{ |
{ |
1000 |
/* An exception occurred, which is already stored in the thread */ |
/* An exception occurred, which is already stored in the thread */ |
1004 |
{ |
{ |
1005 |
/* Clear the native return value, because we cannot assume |
/* Clear the native return value, because we cannot assume |
1006 |
that the native caller knows how to handle exceptions */ |
that the native caller knows how to handle exceptions */ |
1007 |
size = ILSizeOfType(thread, type); |
size = ILSizeOfType(params->thread, type); |
1008 |
ILMemZero(result, size); |
ILMemZero(params->result, size); |
1009 |
|
} |
1010 |
|
} |
1011 |
|
} |
1012 |
|
|
1013 |
|
/* |
1014 |
|
* Invoke the delegate from a new thread. |
1015 |
|
*/ |
1016 |
|
static void *_DelegateInvokeFromNewThread(void *params) |
1017 |
|
{ |
1018 |
|
ILThread *thread = ILThreadSelf(); |
1019 |
|
ILClassPrivate *classPrivate = GetObjectClassPrivate(((ILDelegateInvokeParams *)params)->delegate); |
1020 |
|
ILExecProcess *process = classPrivate->process; |
1021 |
|
|
1022 |
|
if((((ILDelegateInvokeParams *)params)->thread = ILThreadRegisterForManagedExecution(process, thread))) |
1023 |
|
{ |
1024 |
|
_DelegateInvoke((ILDelegateInvokeParams *)params); |
1025 |
|
ILThreadUnregisterForManagedExecution(thread); |
1026 |
|
} |
1027 |
|
return 0; |
1028 |
|
} |
1029 |
|
|
1030 |
|
/* |
1031 |
|
* Invoke a delegate from a closure. |
1032 |
|
*/ |
1033 |
|
static void DelegateInvoke(ffi_cif *cif, void *result, |
1034 |
|
void **args, void *delegate) |
1035 |
|
{ |
1036 |
|
ILThread *thread = ILThreadSelf(); |
1037 |
|
ILClassPrivate *classPrivate = GetObjectClassPrivate(delegate); |
1038 |
|
ILExecProcess *process = classPrivate->process; |
1039 |
|
ILDelegateInvokeParams params; |
1040 |
|
|
1041 |
|
params.thread = 0; |
1042 |
|
params.cif = cif; |
1043 |
|
params.result = result; |
1044 |
|
params.args = args; |
1045 |
|
params.delegate = (System_Delegate *)delegate; |
1046 |
|
if(!thread) |
1047 |
|
{ |
1048 |
|
/* callback was invoked by a non pnet thread. */ |
1049 |
|
|
1050 |
|
ILThreadRunSelf(_DelegateInvokeFromNewThread, (void *)¶ms); |
1051 |
|
} |
1052 |
|
else |
1053 |
|
{ |
1054 |
|
params.thread = _ILExecThreadFromThread(thread); |
1055 |
|
|
1056 |
|
if(params.thread) |
1057 |
|
{ |
1058 |
|
IL_BEGIN_EXECPROCESS_SWITCH(params.thread, process) |
1059 |
|
_DelegateInvoke(¶ms); |
1060 |
|
IL_END_EXECPROCESS_SWITCH(params.thread) |
1061 |
|
} |
1062 |
|
else |
1063 |
|
{ |
1064 |
|
/* thread is not registerd for managed execution */ |
1065 |
|
if((params.thread = ILThreadRegisterForManagedExecution(process, thread))) |
1066 |
|
{ |
1067 |
|
|
1068 |
|
_DelegateInvoke(¶ms); |
1069 |
|
ILThreadUnregisterForManagedExecution(thread); |
1070 |
|
} |
1071 |
} |
} |
1072 |
} |
} |
1073 |
} |
} |