[Mono-dev] [PATCH] Optimizations for FileSystemWatcher and MulticastDelegate
Juraj Skripsky
js at hotfeet.ch
Thu Jul 19 14:36:52 EDT 2007
Hello,
I thought about it some more. Yes, you're right, returning an array
containing this.Clone() is the safest thing to do. Otherwise we might
mix up the chaining...
I'm looking into a more MS.net-like implementation (using an
'invocationList' array instead of a linked list). I think the resulting
code will be much simpler. And the invocation of a chain will be done
iteratively rather than recursively, which is much nicer.
Right now, I'm trying to wrap my head around
mono_marshal_get_delegate_invoke() in marshal.c...
- Juraj
On Thu, 2007-07-19 at 20:20 +0200, Andreas Färber wrote:
> Hello,
>
> Am 19.07.2007 um 18:34 schrieb Juraj Skripsky:
>
> > On Thu, 2007-07-19 at 12:04 -0400, Miguel de Icaza wrote:
> >> can you explain the rationale for the changes in
> >> MulticastDelegate,
> >> for example, why not return this.Clone () instead of the new
> >> construct
> >> new Delegate [1] { this }?
> >
> > The new code distinguishes between two cases (see the diff below):
> >
> > a) We don't have a chain, the only delegate to return is 'this'
> > (or rather an array only containing one element: 'this').
> >
> > The old code did far too much work in this case:
> > - clone this
> > - build forward linked list (0 iterations as d.prev == null)
> > - enter the if-block (as d.kpm_next was set to null)
> > - clone the clone
> > - set other.prev and other.kpm_next to null (they already are!)
> > - return "new Delegate[1] { other }" where other.Equals(this)
> >
> > So it cloned the delegate twice and finally returned an
> > array containing the second clone (which equals 'this').
> >
> > The new code does the same without all the unnecessary steps.
> >
> > b) This stays the same.
> >
> >
> > public sealed override Delegate[] GetInvocationList ()
> > {
> > - MulticastDelegate d;
> > - d = (MulticastDelegate) this.Clone ();
> > + // does the list only contain ourself?
> > + if (prev == null)
> > + return new Delegate [1] { this };
> > +
> > + // walk the list backwards, connecting the links the other
> > way
> > + MulticastDelegate d = this;
> > for (d.kpm_next = null; d.prev != null; d = d.prev)
> > d.prev.kpm_next = d;
> >
> > - if (d.kpm_next == null) {
> > - MulticastDelegate other = (MulticastDelegate) d.Clone ();
> > - other.prev = null;
> > - other.kpm_next = null;
> > - return new Delegate [1] { other };
> > - }
> > -
> > + // walk the list, building the invocation list
> > ArrayList list = new ArrayList ();
> > for (; d != null; d = d.kpm_next) {
> > MulticastDelegate other = (MulticastDelegate) d.Clone ();
>
> I concur with Miguel: The original code apparently returns this.Clone
> ().Clone() but intended was probably this.Clone(), not this. In
> general that's a question of reference equality, safety etc.
>
> Andreas
>
More information about the Mono-devel-list
mailing list