river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peter_firmst...@apache.org
Subject svn commit: r1468119 [10/15] - in /river/jtsk/skunk/qa_refactor/trunk: qa/src/com/sun/jini/qa/harness/ qa/src/com/sun/jini/test/impl/mahalo/ qa/src/com/sun/jini/test/resources/ qa/src/com/sun/jini/test/share/ qa/src/com/sun/jini/test/spec/javaspace/con...
Date Mon, 15 Apr 2013 15:26:46 GMT
Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/EventRegistrationWatcher.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/EventRegistrationWatcher.java?rev=1468119&r1=1468118&r2=1468119&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/EventRegistrationWatcher.java
(original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/EventRegistrationWatcher.java
Mon Apr 15 15:26:44 2013
@@ -1,380 +1,380 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.sun.jini.outrigger;
-
-import java.io.IOException;
-import java.rmi.RemoteException;
-import java.rmi.MarshalledObject;
-import net.jini.core.event.RemoteEventListener;
-import net.jini.core.event.RemoteEvent;
-import net.jini.core.event.UnknownEventException;
-import net.jini.id.Uuid;
-import net.jini.security.ProxyPreparer;
-import net.jini.space.JavaSpace;
-import com.sun.jini.landlord.LeasedResource;
-
-/**
- * Subclass of <code>TransitionWatcher</code> for event
- * registrations. Also represents the registration itself.
- */
-abstract class EventRegistrationWatcher extends TransitionWatcher 
-    implements EventRegistrationRecord
-{
-    /** 
-     * The current expiration time of the registration
-     * Protected, but only for use by subclasses.
-     */
-    volatile long expiration;
-
-    /** 
-     * The UUID that identifies this registration 
-     * Protected, but only for use by subclasses.
-     * Should not be changed.
-     */
-    Uuid cookie;
-
-    /**
-     * The handback associated with this registration.
-     * Protected, but only for use by subclasses.
-     * Should not be changed.
-     */
-    MarshalledObject handback;
-
-    /** 
-     * The event ID associated with this registration
-     * Protected, but only for use by subclasses.
-     * Should not be changed.
-     */
-    long eventID;
-
-    /** 
-     * The current sequence number. 
-     */
-    private long currentSeqNum = 0;
-
-    /**
-     * The sequence number of the last event successfully 
-     * delivered.  Protected, but only for use by subclasses.
-     */
-    long lastSeqNumDelivered = -1;
-
-    /**
-     * The <code>TemplateHandle</code> associated with this
-     * watcher.
-     */
-    private TemplateHandle owner;
-
-    /**
-     * Used during log recovery to create a mostly empty
-     * <code>EventRegistrationWatcher</code>.  
-     * <p> 
-     * Note, we set the time stamp and tie-breaker here instead of
-     * getting them from the log. This means they will be inconstant
-     * with their value from the last VM we were in, but since they
-     * never leak out and events are read-only anyway this should not
-     * be a problem (this also allows us to keep the tie-breaker and
-     * time stamp in final fields).
-     *
-     * @param timestamp the value that is used
-     *        to sort <code>TransitionWatcher</code>s.
-     * @param startOrdinal the highest ordinal associated
-     *        with operations that are considered to have occurred 
-     *        before the operation associated with this watcher.
-     * @param currentSeqNum Sequence number to start with.
-     */
-    EventRegistrationWatcher(long timestamp, long startOrdinal, 
-			     long currentSeqNum) 
-    {
-	super(timestamp, startOrdinal);
-	this.currentSeqNum = currentSeqNum;
-    }
-
-    /**
-     * Create a new <code>EventRegistrationWatcher</code>.
-     * @param timestamp the value that is used
-     *        to sort <code>TransitionWatcher</code>s.
-     * @param startOrdinal the highest ordinal associated
-     *        with operations that are considered to have occurred 
-     *        before the operation associated with this watcher.
-     * @param cookie The unique identifier associated
-     *        with this watcher. Must not be <code>null</code>.
-     * @param handback The handback object that
-     *        should be sent along with event
-     *        notifications to the the listener.
-     * @param eventID The event ID for event type
-     *        represented by this object.
-     * @throws NullPointerException if the <code>cookie</code>
-     *        argument is <code>null</code>.
-     */
-    EventRegistrationWatcher(long timestamp, long startOrdinal, Uuid cookie,
-	MarshalledObject handback, long eventID)
-    {
-	super(timestamp, startOrdinal);
-
-	if (cookie == null)
-	    throw new NullPointerException("cookie must be non-null");
-
-	this.cookie = cookie;
-	this.handback = handback;
-	this.eventID = eventID;
-    }
-
-    /**
-     * Process the given transition by queuing up a task with the
-     * notifier for event delivery. Assumes the passed entry matches
-     * the template in the <code>TemplateHandle</code> associated with
-     * this watcher and that <code>isInterested</code> returned
-     * <code>true</code>. If <code>remove</code> has been called
or
-     * the expiration time of this watcher has passed, this call
-     * should have no effect. This call may cause the watcher to be
-     * removed.
-     * @param transition A <code>EntryTransition</code> that
-     *              describes the transition and what
-     *              entry is transitioning. This method
-     *              will assume that <code>transition.getHandle</code>
-     *              returns a non-null value.
-     * @param now   An estimate of the current time (not the time
-     *              when the event occured).
-     * @throws NullPointerException if <code>transition</code> is 
-     *         <code>null</code>.  
-     */
-    void process(EntryTransition transition, long now) {
-	boolean doneFor = false;
-
-	// lock before checking the time and so we can update currentSeqNum
-	synchronized (this) {
-	    if (owner == null) 
-		return; // Must have been removed
-
-	    if (now > expiration) {
-		doneFor = true;
-	    } else {
-		currentSeqNum++;
-		owner.getServer().enqueueDelivery(new BasicEventSender());
-	    }
-	}
-
-	if (doneFor)
-	    cancel();
-    }
-
-
-    /**
-     * Return the remote listener associated with this 
-     * <code>EventRegistrationWatcher</code>. Optionally
-     * prepare the listener if it has been recovered from
-     * the store and not yet re-prepared.
-     * @return the remote listener associated with this 
-     * <code>EventRegistrationWatcher</code>. 
-     * @throws IOException if the listener can not
-     *         be unmarshalled. May throw {@link RemoteException}
-     *         if the call to the preparer does
-     * @throws ClassNotFoundException if the listener
-     *         needs to be unmarshalled and a necessary
-     *         class can not be found.
-     * @throws SecurityException if the <code>prepareProxy</code>
-     *         call does.
-     */
-    abstract RemoteEventListener getListener(ProxyPreparer preparer)
-	throws ClassNotFoundException, IOException;
-
-    /**
-     * Associate a <code>TemplateHandle</code> with this object.  May
-     * only be called once on any given
-     * <code>EventRegistrationWatcher</code> instance.
-     *
-     * @param h The <code>TemplateHandle</code> associated
-     *          with this watcher.
-     * @return <code>true</code> if the handle was succfully added,
-     *         and <code>false</code> if the watcher has already
-     *         been removed.
-     * @throws NullPointerException if <code>h</code> is 
-     *        <code>null</code> 
-     */
-    boolean addTemplateHandle(TemplateHandle h) {
-	if (h == null) 
-	    throw 
-		new NullPointerException("TemplateHandle must be non-null");
-        synchronized (this){
-            if (owner != null)
-                throw new AssertionError("Can only call addTemplateHandle once");
-
-            owner = h;
-        }
-	return true;
-    }
-
-    /**
-     * Set the expiration time of this object.  This method may be
-     * called before <code>setTemplateHandle</code> is called.
-     * Assumes locking is handled by the caller.
-     * @param newExpiration The expiration time.
-     */
-    public void setExpiration(long newExpiration) {
-	expiration = newExpiration;
-    }
-
-    public long getExpiration() {
-	return expiration;
-    }
-
-    /**
-     * Get the unique identifier associated with this object.  This
-     * method may be called before <code>setTemplateHandle</code> is
-     * called. 
-     * @return The unique identifier associated with this
-     * watcher.
-     */
-    public Uuid getCookie() {
-	return cookie;
-    }
-
-    /**
-     * Overridden by subclasses if there is any cleanup work they need
-     * to do as part of <code>cancel</code> or
-     * <code>removeIfExpired</code>. Called after releasing the lock
-     * on <code>this</code>.  Will be called at most once.  
-     * @param owner A reference to the owner.
-     * @param expired <code>true</code> if being called from 
-     *        <code>removeIfExpired</code> and false otherwise. 
-     */
-    void cleanup(TemplateHandle owner, boolean expired) 
-    {}
-
-    /**
-     * The heavy lifting of removing ourselves.
-     * @param now The current time (or a bit earlier).
-     * @param doIt If <code>true</code> ignore
-     *             <code>now</code> and just remove <code>this</code>
-     *             object.
-     * @return <code>true</code> if this call removed
-     *         <code>this</code> object, <code>false</code> if
-     *         it had already been done. Should be ignored if 
-     *         <code>doIt</code> is <code>false</code>.
-     */
-    private boolean doRemove(long now, boolean doIt) {
-	final TemplateHandle owner;
-	synchronized (this) {
-	    if (this.owner == null)
-		return false; // already removed
-
-	    // Is this a force, or past our expiration?
-	    if (!doIt && (now < expiration))
-		return false; // don't remove, not our time
-
-	    owner = this.owner;
-	    expiration = Long.MIN_VALUE; //Make sure no one tries to renew us
-	    this.owner = null;       //We might stick around don't hold owner
-	}
-
-	cleanup(owner, !doIt);
-	owner.getServer().removeEventRegistration(this);	    
-	owner.removeTransitionWatcher(this);	
-	return true; // we did the deed
-    }
-
-    void removeIfExpired(long now) {
-	doRemove(now, false);
-    }
-
-    public boolean cancel() {
-	return doRemove(0, true);
-    }
-
-    /**
-     * Common implementation of <code>EventSender</code>.
-     */
-    private class BasicEventSender implements EventSender {
-	public void sendEvent(JavaSpace source, long now, ProxyPreparer preparer)
-	    throws UnknownEventException, IOException, ClassNotFoundException
-	{
-	    boolean doneFor = false;
-	    long seqNum = -1;
-
-	    synchronized (EventRegistrationWatcher.this) {
-		if (owner == null)
-		    return; // Our watcher must have been removed, we're done
-
-		if (getExpiration() < now) {
-		    doneFor = true; // Our watcher is expired, remove it
-		} else if (currentSeqNum <= lastSeqNumDelivered) {
-		    return; // Someone already sent our event, we're done
-		} else {
-		    // We need to send an event!
-		    seqNum = currentSeqNum;
-		}
-	    
-
-                // cancel is a synchronized method with the same lock.
-                if (doneFor) {
-                    cancel();
-                    return;
-                }
-
-                /* The only way to get here is through a path that sets
-                 * seqNum to the non-initial values
-                 */
-                assert seqNum != -1;
-
-
-
-                // success!, update lastSeqNumDelivered, but don't go backward
-	    
-		if (seqNum > lastSeqNumDelivered)
-		    lastSeqNumDelivered = seqNum;
-	    }
-            
-             /* If we are here then we need to send an event (probably
-	     * someone could have sent our event between the time
-	     * we released the lock and now).
-	     */
-	    getListener(preparer).notify(
-		new RemoteEvent(source, eventID, seqNum, handback));
-	}
-	
-	
-	public void cancelRegistration() {
-	    cancel();
-	}
-
-	/**
-	 * Return the <code>EventRegistrationWatcher</code> this
-	 * object is part of (exits because
-	 * <code>(BasicEventSender)other).EventRegistrationWatcher.
-	 * this</code> does not work.
-	 */
-	private EventRegistrationWatcher getOwner() {
-	    return EventRegistrationWatcher.this;
-	}
-
-	/**
-	 * Run after another event sender if it is for the same
-	 * registration. No sense sending the same event twice. Don't
-	 * care which one goes first (though the second probably won't
-	 * run since <code>lastSeqNumDelivered</code> will probably
-	 * equal <code>currentSeqNum</code> when it runs).  
-	 */
-	public boolean runAfter(EventSender other) {
-	    if (!(other instanceof BasicEventSender))
-		return false;
-
-	    return EventRegistrationWatcher.this ==
-		((BasicEventSender)other).getOwner();
-	}
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.jini.outrigger;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.rmi.MarshalledObject;
+import net.jini.core.event.RemoteEventListener;
+import net.jini.core.event.RemoteEvent;
+import net.jini.core.event.UnknownEventException;
+import net.jini.id.Uuid;
+import net.jini.security.ProxyPreparer;
+import net.jini.space.JavaSpace;
+import com.sun.jini.landlord.LeasedResource;
+
+/**
+ * Subclass of <code>TransitionWatcher</code> for event
+ * registrations. Also represents the registration itself.
+ */
+abstract class EventRegistrationWatcher extends TransitionWatcher 
+    implements EventRegistrationRecord
+{
+    /** 
+     * The current expiration time of the registration
+     * Protected, but only for use by subclasses.
+     */
+    volatile long expiration;
+
+    /** 
+     * The UUID that identifies this registration 
+     * Protected, but only for use by subclasses.
+     * Should not be changed.
+     */
+    Uuid cookie;
+
+    /**
+     * The handback associated with this registration.
+     * Protected, but only for use by subclasses.
+     * Should not be changed.
+     */
+    MarshalledObject handback;
+
+    /** 
+     * The event ID associated with this registration
+     * Protected, but only for use by subclasses.
+     * Should not be changed.
+     */
+    long eventID;
+
+    /** 
+     * The current sequence number. 
+     */
+    private long currentSeqNum = 0;
+
+    /**
+     * The sequence number of the last event successfully 
+     * delivered.  Protected, but only for use by subclasses.
+     */
+    long lastSeqNumDelivered = -1;
+
+    /**
+     * The <code>TemplateHandle</code> associated with this
+     * watcher.
+     */
+    private TemplateHandle owner;
+
+    /**
+     * Used during log recovery to create a mostly empty
+     * <code>EventRegistrationWatcher</code>.  
+     * <p> 
+     * Note, we set the time stamp and tie-breaker here instead of
+     * getting them from the log. This means they will be inconstant
+     * with their value from the last VM we were in, but since they
+     * never leak out and events are read-only anyway this should not
+     * be a problem (this also allows us to keep the tie-breaker and
+     * time stamp in final fields).
+     *
+     * @param timestamp the value that is used
+     *        to sort <code>TransitionWatcher</code>s.
+     * @param startOrdinal the highest ordinal associated
+     *        with operations that are considered to have occurred 
+     *        before the operation associated with this watcher.
+     * @param currentSeqNum Sequence number to start with.
+     */
+    EventRegistrationWatcher(long timestamp, long startOrdinal, 
+			     long currentSeqNum) 
+    {
+	super(timestamp, startOrdinal);
+	this.currentSeqNum = currentSeqNum;
+    }
+
+    /**
+     * Create a new <code>EventRegistrationWatcher</code>.
+     * @param timestamp the value that is used
+     *        to sort <code>TransitionWatcher</code>s.
+     * @param startOrdinal the highest ordinal associated
+     *        with operations that are considered to have occurred 
+     *        before the operation associated with this watcher.
+     * @param cookie The unique identifier associated
+     *        with this watcher. Must not be <code>null</code>.
+     * @param handback The handback object that
+     *        should be sent along with event
+     *        notifications to the the listener.
+     * @param eventID The event ID for event type
+     *        represented by this object.
+     * @throws NullPointerException if the <code>cookie</code>
+     *        argument is <code>null</code>.
+     */
+    EventRegistrationWatcher(long timestamp, long startOrdinal, Uuid cookie,
+	MarshalledObject handback, long eventID)
+    {
+	super(timestamp, startOrdinal);
+
+	if (cookie == null)
+	    throw new NullPointerException("cookie must be non-null");
+
+	this.cookie = cookie;
+	this.handback = handback;
+	this.eventID = eventID;
+    }
+
+    /**
+     * Process the given transition by queuing up a task with the
+     * notifier for event delivery. Assumes the passed entry matches
+     * the template in the <code>TemplateHandle</code> associated with
+     * this watcher and that <code>isInterested</code> returned
+     * <code>true</code>. If <code>remove</code> has been called
or
+     * the expiration time of this watcher has passed, this call
+     * should have no effect. This call may cause the watcher to be
+     * removed.
+     * @param transition A <code>EntryTransition</code> that
+     *              describes the transition and what
+     *              entry is transitioning. This method
+     *              will assume that <code>transition.getHandle</code>
+     *              returns a non-null value.
+     * @param now   An estimate of the current time (not the time
+     *              when the event occured).
+     * @throws NullPointerException if <code>transition</code> is 
+     *         <code>null</code>.  
+     */
+    void process(EntryTransition transition, long now) {
+	boolean doneFor = false;
+
+	// lock before checking the time and so we can update currentSeqNum
+	synchronized (this) {
+	    if (owner == null) 
+		return; // Must have been removed
+
+	    if (now > expiration) {
+		doneFor = true;
+	    } else {
+		currentSeqNum++;
+		owner.getServer().enqueueDelivery(new BasicEventSender());
+	    }
+	}
+
+	if (doneFor)
+	    cancel();
+    }
+
+
+    /**
+     * Return the remote listener associated with this 
+     * <code>EventRegistrationWatcher</code>. Optionally
+     * prepare the listener if it has been recovered from
+     * the store and not yet re-prepared.
+     * @return the remote listener associated with this 
+     * <code>EventRegistrationWatcher</code>. 
+     * @throws IOException if the listener can not
+     *         be unmarshalled. May throw {@link RemoteException}
+     *         if the call to the preparer does
+     * @throws ClassNotFoundException if the listener
+     *         needs to be unmarshalled and a necessary
+     *         class can not be found.
+     * @throws SecurityException if the <code>prepareProxy</code>
+     *         call does.
+     */
+    abstract RemoteEventListener getListener(ProxyPreparer preparer)
+	throws ClassNotFoundException, IOException;
+
+    /**
+     * Associate a <code>TemplateHandle</code> with this object.  May
+     * only be called once on any given
+     * <code>EventRegistrationWatcher</code> instance.
+     *
+     * @param h The <code>TemplateHandle</code> associated
+     *          with this watcher.
+     * @return <code>true</code> if the handle was succfully added,
+     *         and <code>false</code> if the watcher has already
+     *         been removed.
+     * @throws NullPointerException if <code>h</code> is 
+     *        <code>null</code> 
+     */
+    boolean addTemplateHandle(TemplateHandle h) {
+	if (h == null) 
+	    throw 
+		new NullPointerException("TemplateHandle must be non-null");
+        synchronized (this){
+            if (owner != null)
+                throw new AssertionError("Can only call addTemplateHandle once");
+
+            owner = h;
+        }
+	return true;
+    }
+
+    /**
+     * Set the expiration time of this object.  This method may be
+     * called before <code>setTemplateHandle</code> is called.
+     * Assumes locking is handled by the caller.
+     * @param newExpiration The expiration time.
+     */
+    public void setExpiration(long newExpiration) {
+	expiration = newExpiration;
+    }
+
+    public long getExpiration() {
+	return expiration;
+    }
+
+    /**
+     * Get the unique identifier associated with this object.  This
+     * method may be called before <code>setTemplateHandle</code> is
+     * called. 
+     * @return The unique identifier associated with this
+     * watcher.
+     */
+    public synchronized Uuid getCookie() {
+	return cookie;
+    }
+
+    /**
+     * Overridden by subclasses if there is any cleanup work they need
+     * to do as part of <code>cancel</code> or
+     * <code>removeIfExpired</code>. Called after releasing the lock
+     * on <code>this</code>.  Will be called at most once.  
+     * @param owner A reference to the owner.
+     * @param expired <code>true</code> if being called from 
+     *        <code>removeIfExpired</code> and false otherwise. 
+     */
+    void cleanup(TemplateHandle owner, boolean expired) 
+    {}
+
+    /**
+     * The heavy lifting of removing ourselves.
+     * @param now The current time (or a bit earlier).
+     * @param doIt If <code>true</code> ignore
+     *             <code>now</code> and just remove <code>this</code>
+     *             object.
+     * @return <code>true</code> if this call removed
+     *         <code>this</code> object, <code>false</code> if
+     *         it had already been done. Should be ignored if 
+     *         <code>doIt</code> is <code>false</code>.
+     */
+    private boolean doRemove(long now, boolean doIt) {
+	final TemplateHandle owner;
+	synchronized (this) {
+	    if (this.owner == null)
+		return false; // already removed
+
+	    // Is this a force, or past our expiration?
+	    if (!doIt && (now < expiration))
+		return false; // don't remove, not our time
+
+	    owner = this.owner;
+	    expiration = Long.MIN_VALUE; //Make sure no one tries to renew us
+	    this.owner = null;       //We might stick around don't hold owner
+	}
+
+	cleanup(owner, !doIt);
+	owner.getServer().removeEventRegistration(this);	    
+	owner.removeTransitionWatcher(this);	
+	return true; // we did the deed
+    }
+
+    void removeIfExpired(long now) {
+	doRemove(now, false);
+    }
+
+    public boolean cancel() {
+	return doRemove(0, true);
+    }
+
+    /**
+     * Common implementation of <code>EventSender</code>.
+     */
+    private class BasicEventSender implements EventSender {
+	public void sendEvent(JavaSpace source, long now, ProxyPreparer preparer)
+	    throws UnknownEventException, IOException, ClassNotFoundException
+	{
+	    boolean doneFor = false;
+	    long seqNum = -1;
+
+	    synchronized (EventRegistrationWatcher.this) {
+		if (owner == null)
+		    return; // Our watcher must have been removed, we're done
+
+		if (getExpiration() < now) {
+		    doneFor = true; // Our watcher is expired, remove it
+		} else if (currentSeqNum <= lastSeqNumDelivered) {
+		    return; // Someone already sent our event, we're done
+		} else {
+		    // We need to send an event!
+		    seqNum = currentSeqNum;
+		}
+	    
+
+                // cancel is a synchronized method with the same lock.
+                if (doneFor) {
+                    cancel();
+                    return;
+                }
+
+                /* The only way to get here is through a path that sets
+                 * seqNum to the non-initial values
+                 */
+                assert seqNum != -1;
+
+
+
+                // success!, update lastSeqNumDelivered, but don't go backward
+	    
+		if (seqNum > lastSeqNumDelivered)
+		    lastSeqNumDelivered = seqNum;
+	    }
+            
+             /* If we are here then we need to send an event (probably
+	     * someone could have sent our event between the time
+	     * we released the lock and now).
+	     */
+	    getListener(preparer).notify(
+		new RemoteEvent(source, eventID, seqNum, handback));
+	}
+	
+	
+	public void cancelRegistration() {
+	    cancel();
+	}
+
+	/**
+	 * Return the <code>EventRegistrationWatcher</code> this
+	 * object is part of (exits because
+	 * <code>(BasicEventSender)other).EventRegistrationWatcher.
+	 * this</code> does not work.
+	 */
+	private EventRegistrationWatcher getOwner() {
+	    return EventRegistrationWatcher.this;
+	}
+
+	/**
+	 * Run after another event sender if it is for the same
+	 * registration. No sense sending the same event twice. Don't
+	 * care which one goes first (though the second probably won't
+	 * run since <code>lastSeqNumDelivered</code> will probably
+	 * equal <code>currentSeqNum</code> when it runs).  
+	 */
+	public boolean runAfter(EventSender other) {
+	    if (!(other instanceof BasicEventSender))
+		return false;
+
+	    return EventRegistrationWatcher.this ==
+		((BasicEventSender)other).getOwner();
+	}
+    }
+}



Mime
View raw message