[Mono-list] [review] delegates are cascading.
Daniel Stodden
stodden@in.tum.de
09 Mar 2002 10:55:33 +0100
--=-gm6N0zDFUFQeOD6UTxSf
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
yay.
attached two lengthy patches over mono/ and mcs/
to make MuticastDelegate::Invoke() run smoothly over combined
delegates. Remove() is missing but I'll finish that over the next days.
i'm pretty certain it is solid, but since it changes quite
bit in emit-x86..
please, if someone review this and tell me whether its okay to check in.
regards,
dns
abstract: this removes the array-based approach in favour of a reverse,
self-contained linked list. [emit-x86].Invoke() then recurses over the
contained links.
Why reverse? The docs require Remove() to kill any _last_ occurences of
a combination in the current delegate. any other method needs to
traverse the whole list anyways, so reversing should keep remove more
efficient.
--
___________________________________________________________________________
mailto:stodden@in.tum.de
--=-gm6N0zDFUFQeOD6UTxSf
Content-Disposition: attachment; filename=mono.diff
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1
? @
? build
? doc/pending-classes
Index: mono/interpreter/interp.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/interpreter/interp.c,v
retrieving revision 1.146
diff -u -r1.146 interp.c
--- mono/interpreter/interp.c 2002/03/07 12:40:24 1.146
+++ mono/interpreter/interp.c 2002/03/09 05:50:07
@@ -533,16 +533,16 @@
MonoObject *obj =3D (MonoObject*)frame->obj;
MonoDelegate *delegate =3D (MonoDelegate*)frame->obj;
=20
- mono_class_init (mono_defaults.delegate_class);
+ mono_class_init (mono_defaults.multicastdelegate_class);
=09
if (*name =3D=3D '.' && (strcmp (name, ".ctor") =3D=3D 0) && obj &&
- mono_object_isinst (obj, mono_defaults.delegate_class)) {
+ mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
delegate->target =3D frame->stack_args[0].data.p;
delegate->method_ptr =3D frame->stack_args[1].data.p;
return;
}
if (*name =3D=3D 'I' && (strcmp (name, "Invoke") =3D=3D 0) && obj &&
- mono_object_isinst (obj, mono_defaults.delegate_class)) {
+ mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
MonoPIFunc func;
guchar *code;
MonoMethod *method;
Index: mono/jit/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/jit/Makefile.am,v
retrieving revision 1.15
diff -u -r1.15 Makefile.am
--- mono/jit/Makefile.am 2002/03/07 19:08:11 1.15
+++ mono/jit/Makefile.am 2002/03/09 05:50:07
@@ -25,6 +25,8 @@
$(GMODULE_LIBS) \
-lm
=20
+BUILT_SOURCES =3D codegen-x86.c codegen.h
+
codegen-x86.c codegen.h: x86.brg
../monoburg/monoburg $(srcdir)/x86.brg -d codegen.h > codegen-x86.c
=20
Index: mono/jit/emit-x86.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.61
diff -u -r1.61 emit-x86.c
--- mono/jit/emit-x86.c 2002/03/08 06:08:46 1.61
+++ mono/jit/emit-x86.c 2002/03/09 05:50:07
@@ -918,21 +918,21 @@
if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
MonoClassField *field;
const char *name =3D method->name;
- static guint target_offset =3D 0;
- static guint method_offset =3D 0;
+ static guint target_offset =3D 0, method_offset =3D 0, prev_offset =3D 0=
;
+
guint8 *code;
gboolean delegate =3D FALSE;
=20
- if (method->klass->parent &&=20
- method->klass->parent->parent =3D=3D mono_defaults.delegate_class)
+ if (method->klass->parent =3D=3D mono_defaults.multicastdelegate_class)
delegate =3D TRUE;
=09
if (!target_offset) {
- mono_class_init (mono_defaults.delegate_class);
-
- field =3D mono_class_get_field_from_name (mono_defaults.delegate_class,=
"m_target");
+ mono_class_init (mono_defaults.multicastdelegate_class);
+ field =3D mono_class_get_field_from_name (mono_defaults.multicastdelega=
te_class, "prev");
+ prev_offset =3D field->offset;
+ field =3D mono_class_get_field_from_name (mono_defaults.multicastdelega=
te_class->parent, "m_target");
target_offset =3D field->offset;
- field =3D mono_class_get_field_from_name (mono_defaults.delegate_class,=
"method_ptr");
+ field =3D mono_class_get_field_from_name (mono_defaults.multicastdelega=
te_class->parent, "method_ptr");
method_offset =3D field->offset;
}
=09
@@ -951,6 +951,8 @@
x86_mov_reg_membase (code, X86_EDX, X86_EBP, 16, 4);
/* store method_ptr */
x86_mov_membase_reg (code, X86_EAX, method_offset, X86_EDX, 4);=20
+ /* set prev to zero */
+ x86_mov_membase_imm (code, X86_EAX, prev_offset, 0, 4);=20
=20
x86_leave (code);
x86_ret (code);
@@ -958,9 +960,16 @@
g_assert ((code - (guint8*)addr) < 32);
=20
} else if (delegate && *name =3D=3D 'I' && (strcmp (name, "Invoke") =3D=
=3D 0)) {
+ /*
+ * Invoke( args .. ) {
+ * if ( prev )
+ * prev.Invoke();
+ * return this.<m_target>( args );
+ * }
+ */
MonoMethodSignature *csig =3D method->signature;
- int i, arg_size, target, this_pos =3D 4;
- guint8 *source;
+ guint8 *br[2], *pos[2];
+ int i, arg_size, this_pos =3D 4;
=09
if (csig->ret->type =3D=3D MONO_TYPE_VALUETYPE) {
g_assert (!csig->ret->byref);
@@ -978,51 +987,87 @@
}
=20
addr =3D g_malloc (64 + arg_size);
-
- for (i =3D 0; i < 2; i ++) {
- int j;
=20
- code =3D addr;
- /* load the this pointer */
- x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
- /* load mtarget */
- x86_mov_reg_membase (code, X86_EDX, X86_EAX, target_offset, 4);=20
- /* check if zero (static method call without this pointer) */
- x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
- x86_branch32 (code, X86_CC_EQ, target, TRUE);=20
- source =3D code;
-
- /* virtual delegate methods: we have to replace the this pointer=20
- * withe the actual target */
- x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4);=20
- /* jump to method_ptr() */
- x86_jump_membase (code, X86_EAX, method_offset);
-
- /* static delegate methods: we have to remove the this pointer=20
- * from the activation frame - I do this do creating a new=20
- * stack frame an copy all arguments except the this pointer */
-
- target =3D code - source;
- g_assert ((arg_size & 3) =3D=3D 0);
- for (j =3D 0; j < (arg_size>>2); j++) {
- x86_push_membase (code, X86_ESP, (arg_size + this_pos));
- }
+ code =3D addr;
+ /* load the this pointer */
+ x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
+ =09
+ /* load prev */
+ x86_mov_reg_membase (code, X86_EDX, X86_EAX, prev_offset, 4);
+ //x86_mov_reg_imm (code, X86_EDX, 0);
+
+ /* prev =3D=3D 0 ? */
+ x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+ br[0] =3D code; x86_branch32 (code, X86_CC_EQ, 0, TRUE );
+ pos[0] =3D code;
+
+ for ( i =3D 0; i < (arg_size>>2); i++ )
+ x86_push_membase( code, X86_ESP, (arg_size + this_pos) );
+ x86_push_reg( code, X86_EAX );
+ x86_push_reg( code, X86_EDX );
+ if (this_pos =3D=3D 8)
+ x86_push_membase (code, X86_ESP, (arg_size + 4));
+ br[1] =3D code; x86_call_imm( code, 0 );
+ pos[1] =3D code; x86_call_imm( br[1], addr - pos[1] );
+ if (this_pos =3D=3D 8)=20
+ x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 8);
+ else
+ x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
+ x86_pop_reg( code, X86_EAX );
+ =09
+ /* prev !=3D 0 */=20
+ x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE );
+ =09
+ /* load mtarget */
+ x86_mov_reg_membase (code, X86_EDX, X86_EAX, target_offset, 4);=20
+ /* mtarget =3D=3D 0 ? */
+ x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+ br[0] =3D code; x86_branch32 (code, X86_CC_EQ, 0, TRUE);
+ pos[0] =3D code;
+
+ /*=20
+ * virtual delegate methods: we have to
+ * replace the this pointer with the actual
+ * target
+ */
+ x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4);=20
+ /* jump to method_ptr() */
+ x86_jump_membase (code, X86_EAX, method_offset);
+
+ /* mtarget !=3D 0 */=20
+ x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE);
+ /*=20
+ * static delegate methods: we have to remove
+ * the this pointer from the activation frame
+ * - I do this creating a new stack frame anx
+ * copy all arguments except the this pointer
+ */
+ g_assert ((arg_size & 3) =3D=3D 0);
+ for (i =3D 0; i < (arg_size>>2); i++) {
+ x86_push_membase (code, X86_ESP, (arg_size + this_pos));
+ }
=20
- if (this_pos =3D=3D 8)=20
- x86_push_membase (code, X86_ESP, (arg_size + 4));
- =09
- x86_call_membase (code, X86_EAX, method_offset);
+ if (this_pos =3D=3D 8)
+ x86_push_membase (code, X86_ESP, (arg_size + 4));
+ =09
+ x86_call_membase (code, X86_EAX, method_offset);
+ if ( arg_size ) {
if (this_pos =3D=3D 8)=20
x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
else
x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size);
- =09
- x86_ret (code);
-
}
=20
+ x86_ret (code);
+ =09
g_assert ((code - (guint8*)addr) < (64 + arg_size));
=20
+ if (mono_jit_dump_asm) {
+ char *id =3D g_strdup_printf ("%s.%s_%s", method->klass->name_space,
+ method->klass->name, method->name);
+ mono_disassemble_code( addr, code - (guint8*)addr, id );
+ g_free (id);
+ }
} else {
if (mono_debug_handle)=20
return NULL;
Index: mono/metadata/appdomain.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/appdomain.c,v
retrieving revision 1.14
diff -u -r1.14 appdomain.c
--- mono/metadata/appdomain.c 2002/03/07 12:41:42 1.14
+++ mono/metadata/appdomain.c 2002/03/09 05:50:07
@@ -199,9 +199,9 @@
mono_defaults.corlib, "System", "Array");
g_assert (mono_defaults.array_class !=3D 0);
=20
- mono_defaults.delegate_class =3D mono_class_from_name (
- mono_defaults.corlib, "System", "Delegate");
- g_assert (mono_defaults.delegate_class !=3D 0);
+ mono_defaults.multicastdelegate_class =3D mono_class_from_name (
+ mono_defaults.corlib, "System", "MulticastDelegate");
+ g_assert (mono_defaults.multicastdelegate_class !=3D 0 );
=20
mono_defaults.typehandle_class =3D mono_class_from_name (
mono_defaults.corlib, "System", "RuntimeTypeHandle");
Index: mono/metadata/loader.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/loader.c,v
retrieving revision 1.51
diff -u -r1.51 loader.c
--- mono/metadata/loader.c 2002/02/13 07:44:58 1.51
+++ mono/metadata/loader.c 2002/03/09 05:50:08
@@ -230,7 +230,7 @@
* in delegates constructors you get in user code (native int)
* and in mscorlib (native unsigned int)
*/
- if (klass->parent && klass->parent->parent =3D=3D mono_defaults.delegat=
e_class) {
+ if (klass->parent =3D=3D mono_defaults.multicastdelegate_class) {
for (i =3D 0; i < klass->method.count; ++i) {
MonoMethod *m =3D klass->methods [i];
if (!strcmp (mname, m->name)) {
Index: mono/metadata/loader.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/loader.h,v
retrieving revision 1.16
diff -u -r1.16 loader.h
--- mono/metadata/loader.h 2002/02/13 07:44:58 1.16
+++ mono/metadata/loader.h 2002/03/09 05:50:08
@@ -48,7 +48,7 @@
MonoClass *string_class;
MonoClass *enum_class;
MonoClass *array_class;
- MonoClass *delegate_class;
+ MonoClass *multicastdelegate_class;
MonoClass *typehandle_class;
MonoClass *fieldhandle_class;
MonoClass *methodhandle_class;
Index: mono/metadata/threads.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/threads.c,v
retrieving revision 1.10
diff -u -r1.10 threads.c
--- mono/metadata/threads.c 2002/02/25 11:01:46 1.10
+++ mono/metadata/threads.c 2002/03/09 05:50:09
@@ -119,7 +119,7 @@
this, start);
#endif
=09
- field=3Dmono_class_get_field_from_name(mono_defaults.delegate_class, "met=
hod_ptr");
+ field=3Dmono_class_get_field_from_name(mono_defaults.multicastdelegate_cl=
ass->parent, "method_ptr");
start_func=3D *(gpointer *)(((char *)start) + field->offset);
=09
if(start_func=3D=3DNULL) {
--=-gm6N0zDFUFQeOD6UTxSf
Content-Disposition: attachment; filename=mcs.diff
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1
? class/corlib/Test/StreamWriterTest.temp
? doctools/build
Index: class/corlib/System/Delegate.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mcs/class/corlib/System/Delegate.cs,v
retrieving revision 1.10
diff -u -r1.10 Delegate.cs
--- class/corlib/System/Delegate.cs 2002/03/05 12:08:17 1.10
+++ class/corlib/System/Delegate.cs 2002/03/09 05:49:46
@@ -3,6 +3,7 @@
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
+// Daniel Stodden (stodden@in.tum.de)
//
// (C) Ximian, Inc. http://www.ximian.com
//
@@ -11,6 +12,7 @@
=20
using System;
using System.Globalization;
+using System.Reflection;
using System.Runtime.Serialization;
=20
namespace System {
@@ -19,8 +21,10 @@
public abstract class Delegate : ICloneable, ISerializable {
protected Type target_type;
protected object m_target;
- protected string method;
+ protected string method_name;
protected IntPtr method_ptr;
+ protected MethodInfo method_info;
+ protected bool method_static;
=20
protected Delegate (object target, string method)
{
@@ -33,7 +37,8 @@
this.target_type =3D null;
this.method_ptr =3D IntPtr.Zero;
this.m_target =3D target;
- this.method =3D method;
+ this.method_name =3D method;
+ this.method_static =3D false;
}
=20
protected Delegate (Type target_type, string method)
@@ -47,16 +52,15 @@
this.target_type =3D target_type;
this.method_ptr =3D IntPtr.Zero;
this.m_target =3D null;
- this.method =3D method;
+ this.method_name =3D method;
+ this.method_static =3D true;
}
=20
-#if NOTYET
public MethodInfo Method {
get {
- return null;
+ throw new NotImplementedException();
}
}
-#endif
=20
public object Target {
get {
@@ -64,23 +68,37 @@
}
}
=20
-
//
// Methods
//
+
+ public object DynamicInvoke( object[] args )
+ {
+ return DynamicInvokeImpl( args );
+ }
=20
- public abstract object Clone ();
+ public virtual object DynamicInvokeImpl( object[] args )
+ {
+ return Method.Invoke( m_target, args );
+ }
+
+ public virtual object Clone()
+ {
+ return MemberwiseClone();
+ }
=20
public override bool Equals (object o)
{
- if (!(o is System.Delegate))
+ if ( o =3D=3D null )
return false;
+ =09
+ if ( o.GetType() !=3D this.GetType() )
+ return false;
=20
Delegate d =3D (Delegate) o;
- =09
if ((d.target_type =3D=3D target_type) &&
(d.m_target =3D=3D m_target) &&
- (d.method =3D=3D method))
+ (d.method_name =3D=3D method_name))
return true;
=20
return false;
@@ -88,7 +106,7 @@
=20
public override int GetHashCode ()
{
- return method.GetHashCode ();
+ return method_name.GetHashCode ();
}
=20
// This is from ISerializable
@@ -98,6 +116,15 @@
// TODO: IMPLEMENT ME
}
=20
+ public virtual Delegate[] GetInvocationList()
+ {
+ return new Delegate[] { this };
+ }
+
+ /// <symmary>
+ /// Returns a new MulticastDelegate holding the
+ /// concatenated invocation lists of MulticastDelegates a and b
+ /// </symmary>
public static Delegate Combine (Delegate a, Delegate b)
{
if (a =3D=3D null){
@@ -114,14 +141,54 @@
return a.CombineImpl (b);
}
=20
+ /// <symmary>
+ /// Returns a new MulticastDelegate holding the
+ /// concatenated invocation lists of an Array of MulticastDelegates
+ /// </symmary>
+ public static Delegate Combine( Delegate[] delegates )
+ {
+ Delegate retval =3D null;
+
+ foreach ( Delegate next in delegates ) {
+ retval =3D Combine( retval, next );
+ }
+
+ return retval;
+ }
+
+
protected virtual Delegate CombineImpl (Delegate d)
{
throw new MulticastNotSupportedException ("");
}
-
+ =09
[MonoTODO]
public static Delegate Remove( Delegate source, Delegate value) {
+ if ( source =3D=3D null )
+ return null;
+ =09
+ if ( value =3D=3D null )
+ return source;
+
throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ protected virtual Delegate RemoveImpl(Delegate d)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static bool operator =3D=3D( Delegate a, Delegate b )
+ {
+ if ( (object)a =3D=3D null )
+ return false;
+ return a.Equals( b );
+ }
+
+ public static bool operator !=3D( Delegate a, Delegate b )
+ {
+ return !(a =3D=3D b);
}
}
}
Index: class/corlib/System/MulticastDelegate.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mcs/class/corlib/System/MulticastDelegate.cs,v
retrieving revision 1.9
diff -u -r1.9 MulticastDelegate.cs
--- class/corlib/System/MulticastDelegate.cs 2002/03/07 12:42:17 1.9
+++ class/corlib/System/MulticastDelegate.cs 2002/03/09 05:49:46
@@ -3,36 +3,40 @@
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
+// Daniel Stodden (stodden@in.tum.de)
//
// (C) Ximian, Inc. http://www.ximian.com
//
-// TODO: Mucho left to implement.
+// TODO: Remove Missing
//
=20
using System.Globalization;
+
namespace System {
=20
- public abstract class MulticastDelegate : Delegate {
+ public abstract class MulticastDelegate : Delegate
+ {
+ private MulticastDelegate prev;
=20
- Delegate [] invocation_list;
- =09
protected MulticastDelegate (object target, string method)
: base (target, method)
{
- invocation_list =3D null;
+ prev =3D null;
}
=20
protected MulticastDelegate (Type target_type, string method)
: base (target_type, method)
{
- invocation_list =3D null;
+ prev =3D null;
}
=20
+#if NOTYET
private MulticastDelegate (Type target_type, string method, Delegate [] =
list)
: base (target_type, method)
{
invocation_list =3D (Delegate[])list.Clone ();
}
+#endif
=09
#if NOTYET
public MethodInfo Method {
@@ -42,37 +46,37 @@
}
#endif
=20
+ public override object DynamicInvokeImpl( object[] args )
+ {
+ if ( prev !=3D null )
+ prev.DynamicInvokeImpl( args );
+
+ return base.DynamicInvokeImpl( args );
+ }
+
// <remarks>
// Equals: two multicast delegates are equal if their base is equal
// and their invocations list is equal.
// </remarks>
public override bool Equals (object o)
{
- if (o =3D=3D null)
- return false;
-
- if (!(o is System.MulticastDelegate))
- return false;
-
- if (!base.Equals (o))
+ if ( ! base.Equals( o ) )
return false;
=20
- MulticastDelegate d =3D (MulticastDelegate) o;
-
- if (d.invocation_list =3D=3D null){
- if (invocation_list =3D=3D null)
- return true;
- return false;
- } else if (invocation_list =3D=3D null)
- return false;
-
- int i =3D 0;
- foreach (Delegate del in invocation_list){
- if (del !=3D d.invocation_list [i++])
+ MulticastDelegate d =3D this;
+ MulticastDelegate c =3D (MulticastDelegate) o;
+ do {
+ if ( d !=3D c )
return false;
- }
- =09
- return true;
+ =09
+ c =3D c.prev;
+ d =3D d.prev;
+ } while ( (object)d !=3D null );
+ =09
+ if ( (object)c =3D=3D null )
+ return true;
+
+ return false;
}
=20
//
@@ -82,35 +86,53 @@
{
return base.GetHashCode ();
}
+ =09
+ // <summary>
+ // Return, in order of invocation, the invocation list
+ // of a MulticastDelegate
+ // </summary>
+ public override Delegate[] GetInvocationList()
+ {
+ throw new NotImplementedException();
+ }
=20
// <summary>
- // Combines this MulticastDelegate with the Delegate `follow'.
- // This can combine MulticastDelegates and Delegates
+ // Combines this MulticastDelegate with the (Multicast)Delegate `follo=
w'.
+ // This does _not_ combine with Delegates. ECMA states the whole deleg=
ate
+ // thing should have better been a simple System.Delegate class.
+ // Compiler generated delegates are always MulticastDelegates.
// </summary>
- [MonoTODO]
- protected override Delegate CombineImpl (Delegate follow)
+ protected override Delegate CombineImpl( Delegate follow )
{
+ MulticastDelegate combined, orig, clone;
=09
- throw new NotImplementedException ();
+ if ( this.GetType() !=3D follow.GetType() )
+ throw new ArgumentException( Locale.GetText("Incompatible Delegate Typ=
es") );
=20
- // FIXME: Implement me.
- // This is not as simple to implement, as we can
- // not create an instance of MulticastDelegate.
- //
- // Got to think more about this.
- }
+ combined =3D (MulticastDelegate)follow.Clone();
=20
- public static bool operator =3D=3D (MulticastDelegate a, MulticastDelega=
te b) {
- if ((object)a =3D=3D null) {
- if ((object)b =3D=3D null)
- return false;
- return false;
+ for ( clone =3D combined, orig =3D ((MulticastDelegate)follow).prev;z
+ (object)orig !=3D null; orig =3D orig.prev ) {
+
+ clone.prev =3D (MulticastDelegate)orig.Clone();
+ clone =3D clone.prev;
+ }
+
+ clone.prev =3D (MulticastDelegate)this.Clone();
+
+ for ( clone =3D clone.prev, orig =3D this.prev;
+ (object)orig !=3D null; orig =3D orig.prev ) {
+
+ clone.prev =3D (MulticastDelegate)orig.Clone();
+ clone =3D clone.prev;
}
- return a.Equals (b);
+
+ return combined;
}
=20
- public static bool operator !=3D (MulticastDelegate a, MulticastDelegate=
b) {
- return !(a =3D=3D b);
+ protected override Delegate RemoveImpl( Delegate value )
+ {
+ throw new NotImplementedException();
}
}
}
--=-gm6N0zDFUFQeOD6UTxSf--