Event listener list implementation

Discussion in 'Java' started by Slobodan C, Jan 22, 2004.

  1. Slobodan C

    Slobodan C Guest

    I am looking for java.util.List implementation for event listeners
    that merges several concepts:

    1) Jakarta Commons Collection library has a
    org.apache.commons.collections.FastArrayList which avoid the overhead
    of synchronization using copy-on-write mode. The idea is that when
    dominant ops are reads (such as event listener lists) then it is
    cheaper to copy entire list before changing it to avoid
    synchronization on reads.

    2) Related to (1), when firing events using an iterator, iterator
    object needs to keep traversing the old copy of a list if the list is
    changed during event firings. Although FastArrayList claims to have
    this behaviour, it does the opposite and throws the exception (see
    Appendix A)

    3) As has been discussed many times before, listeners must be
    referenced using a weak reference. Would be nice if the list
    implementation would take care of it internally and caller need not
    worry about it.

    My question is if such an implementation exists some place.

    Sub question: If you think that (1) and (2) are overkill and
    synchronization is simpler and as fast as copy-on-write, tell me why.


    Appendix A:

    From the Commons Collection 2.1 doc,
    org.apache.commons.collections.FastArrayList:

    public Iterator iterator()

    Return an iterator over the elements in this list in proper
    sequence.

    IMPLEMENTATION NOTE - If the list is operating in fast mode, an
    Iterator is returned, and a structural modification to the list is
    made, then the Iterator will continue over the previous contents of
    the list (at the time that the Iterator was created), rather than
    failing due to concurrent modifications.


    Test:

    FastArrayList l = new FastArrayList();

    l.setFast( false );
    l.add("a");
    l.add("b");
    l.add("c");
    l.setFast( true );
    System.out.println("FAST = "+ l.getFast());

    Iterator seq = l.iterator();
    System.out.println("BEFORE "+ seq.next());
    l.add("Z");
    System.out.println("AFTER "+ seq.next());


    FAST = true
    BEFORE a
    java.util.ConcurrentModificationException
    at org.apache.commons.collections.FastArrayList$ListIter.checkMod(Unknown
    Source)
    at org.apache.commons.collections.FastArrayList$ListIter.next(Unknown
    Source)
    at brisi.main(brisi.java:22)
    Exception in thread "main"

    According to the doc I should not get the exception since the list is
    in fast mode. Yet it is thrown and looking at the source it seems to
    be a deliberate check, so no accident. I can only assume that the doc
    hasn't been updated.
     
    Slobodan C, Jan 22, 2004
    #1
    1. Advertising

  2. Slobodan C

    xarax Guest

    "Slobodan C" <> wrote in message
    news:...
    > I am looking for java.util.List implementation for event listeners
    > that merges several concepts:
    >
    > 1) Jakarta Commons Collection library has a
    > org.apache.commons.collections.FastArrayList which avoid the overhead
    > of synchronization using copy-on-write mode. The idea is that when
    > dominant ops are reads (such as event listener lists) then it is
    > cheaper to copy entire list before changing it to avoid
    > synchronization on reads.


    Don't know about this one...

    > 2) Related to (1), when firing events using an iterator, iterator
    > object needs to keep traversing the old copy of a list if the list is
    > changed during event firings. Although FastArrayList claims to have
    > this behaviour, it does the opposite and throws the exception (see
    > Appendix A)


    When I am ready to fire an event, I make an
    array of the current listener list, then
    walk the array. The listener list can change
    while firing the event, but only the listeners
    that were registered at the time of the event
    will be notified. Creating the array is an
    atomic event (synchronized), so it is somewhat
    fast. Walking the array is not synchronized,
    because no other thread has a reference to
    the array.


    > 3) As has been discussed many times before, listeners must be
    > referenced using a weak reference. Would be nice if the list
    > implementation would take care of it internally and caller need not
    > worry about it.


    This is not too hard to create an abstract class
    implementation of the bare bones, then extend it
    with a nested class for handling your specific
    event type. Hide the list as a private field and
    use instance methods to manage adding, removing,
    event firing, etc. Use synchronization as necessary
    in those instance methods. ArrayList is fast, and
    you can wrap the listener elements with a WeakReference.

    > My question is if such an implementation exists some place.
    >
    > Sub question: If you think that (1) and (2) are overkill and
    > synchronization is simpler and as fast as copy-on-write, tell me why.
    >
    >

    /snip/

    What is the minimum functionality that you need? Specify
    each requirement and be certain that it is a *requirement*,
    rather than a "nice to have feature".
     
    xarax, Jan 23, 2004
    #2
    1. Advertising

  3. Slobodan C

    Slobodan C Guest

    "xarax" <> wrote in message news:<AsaQb.24727$>...
    > "Slobodan C" <> wrote in message
    > news:...

    .......
    >
    > > 2) Related to (1), when firing events using an iterator, iterator
    > > object needs to keep traversing the old copy of a list if the list is
    > > changed during event firings. Although FastArrayList claims to have
    > > this behaviour, it does the opposite and throws the exception (see
    > > Appendix A)

    >
    > When I am ready to fire an event, I make an
    > array of the current listener list, then
    > walk the array. The listener list can change
    > while firing the event, but only the listeners
    > that were registered at the time of the event
    > will be notified. Creating the array is an
    > atomic event (synchronized), so it is somewhat
    > fast. Walking the array is not synchronized,
    > because no other thread has a reference to
    > the array.
    >
    >

    .....

    Of course, that it is the traditional solution. However, in practice
    original array list 99% of the times will not be modified while
    iterating over its elements. Thus we end up creating a copy for each
    even firing even though it wasn't necessary.

    (actually 99% above depends on a particular context ...)

    If a system fires a lot of events it adds up to a lot of garbage being
    created at a fast clip!

    So I'd like an implementation that starts out with an optimistic
    assumption that copy is not needed. Then, while iterating over the
    original array if a modification call is made then a copy is made.
    Something like:

    <Event Firing Thread> <Some other Thread>

    Iterator i(a) = listeners(a).iterator();
    fireEvent( i(a).next() );
    ....
    fireEvent( i(a).next() ); listeners(a).add( this );
    .... {copy} listeners(b)
    fireEvent( i(a).next() );
    -->>>> <Handler>
    do stuff
    listeners(b).remove( this
    );
    {copy} listeners(b)
    ....
    fireEvent( i(a).next() ); listeners(a).add( this );
    ....

    This is sort of pseudo-code. The (x) implies a version of a listener
    list. So you can see that regardless of changes on the right the
    iterator keeps traversing original list (view). Regardless of changes
    being made in another thread or one of the handlers, iterator is fine.
    {copy} is meant to show that only at the last moment new copy is made.
    Thus ideal case would be:

    <Event Firing Thread>

    Iterator i(a) = listeners(a).iterator();
    fireEvent( i(a).next() );
    ....
    fireEvent( i(a).next() );
    <done>

    So no copying since there is no need.
     
    Slobodan C, Jan 23, 2004
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sasha Borodin
    Replies:
    0
    Views:
    3,092
    Sasha Borodin
    Jul 28, 2003
  2. Shrish
    Replies:
    1
    Views:
    433
    Thomas Smith
    Oct 16, 2004
  3. Mmm_moo_cows

    Java Event Listener integer problem.

    Mmm_moo_cows, Oct 24, 2004, in forum: Java
    Replies:
    4
    Views:
    825
    Mmm_moo_cows
    Oct 26, 2004
  4. Replies:
    10
    Views:
    777
  5. Mike Scirocco
    Replies:
    4
    Views:
    278
    Mike Scirocco
    Apr 5, 2007
Loading...

Share This Page