Re: [Proxool-developer] CodeReview - AbstractListenerContainer
UNMAINTAINED!
Brought to you by:
billhorsman
From:
<chr...@em...> - 2004-03-13 14:40:31
|
Good :) Thats my piece of verbose code. Have Bill given you commit rights yet? If so feel free to replace it with what you suggest. CHR Bertrand Renuart wrote: > I had a look at the AbstractListenerContainer... and found it much > complex for what it is supposed to do. > > Let's recap the (supposed) requirements: > - fast access to the list of registered listeners - frequent (read); > - must support concurrency; > - add/remove can be slower and are less frequent (update) > > > The following implementation makes use of an object array to store the > reference to registered listeners. > Every time add/remove is called, a new array is created with the new > state - the original is *not modified* but *replaced* by a new one. > This behavior is important since it guarantees that once you got the > array, you know it will *never been modified while you play with it*. > Thanks to this trick, no need for read/write locks and a fast access > to the list ;-) > > The only precaution now is to make sure that only one thread can > access add/remove at a time. This code is protected by synchronized > statement - which is not a penality since modifications are not frequent. > > > Classes extending this container can get access to the list of > registered listener by calling the protected /getListeners()/ method > that returns a reference to the array. > It is now enough to iterate through the array with a simple for loop. > That's another benefit: no need to construct an iterator every time we > have to deliver an event... > > > All this is definitly less expensive than the current implementation > that makes heavy use of synchronized statements :( > > > The (new) code is below. > Feel free to send any comments :) > > > public abstract class AbstractFastListenerContainer implements > ListenerContainerIF > { > static final Log LOG = > LogFactory.getLog(AbstractFastListenerContainer.class); > > private Object[] listeners = EMPTY_LISTENERS; > private static final Object[] EMPTY_LISTENERS = new Object[]{}; > > /** > * @see ListenerContainerIF#addListener(Object) > */ > public synchronized void addListener(Object listener) > { > // create a new array > Object[] newListeners = new Object[listeners.length]; > > // copy listeners currently registered > System.arraycopy(listeners, 0, newListeners, 0, listeners.length); > > // add the new one > newListeners[listeners.length] = listener; > > // commit changes > listeners = newListeners; > } > > > /** > * @see ListenerContainerIF#removeListener(Object) > */ > public synchronized boolean removeListener(Object listener) > { > // find listener to remove in the list > int index=-1; > for(int i=0; i<listeners.length; i++) { > if( listeners[i]==listener ) { > index = i; > break; > } > } > > // not found ? > if( index==-1 ) > return false; > > // create a new array of the right size > Object[] newListeners = new Object[listeners.length-1]; > > // copy registered listeners minus the one to remove > if( index > 0 ) > System.arraycopy(listeners, 0, newListeners, 0, index); > > if( index < listeners.length-1 ) > System.arraycopy(listeners, index+1, newListeners, index, > listeners.length-index-1); > > // commit > listeners = newListeners; > return true; > } > > > /** > * Get a reference to the array containing registered listeners > */ > protected Object[] getListeners() { > return listeners; > } > > > /** > * @see ListenerContainerIF#isEmpty() > */ > public boolean isEmpty() { > return listeners.length==0; > } > } > > > > > |