* Fixed race that (maybe) caused the problems reported by aum on

<http://dev.i2p.net/pipermail/i2p/2004-April/000214.html>;
* slightly revised locking;
* made accept() throw a ConnectException when the I2PServerSocket is closed.
(human)
This commit is contained in:
human
2004-04-14 15:28:02 +00:00
committed by zzz
parent 4cdd42f391
commit d2b09ecfda
2 changed files with 50 additions and 24 deletions

View File

@ -1,5 +1,7 @@
package net.i2p.client.streaming;
import java.net.ConnectException;
import net.i2p.I2PException;
/**
@ -17,10 +19,13 @@ public interface I2PServerSocket {
* connection and the local application wasn't .accept()ing new connections,
* they should get refused (if .accept() doesnt occur in some small period)
*
* @return a connected I2PSocket
*
* @throws I2PException if there is a problem with reading a new socket
* from the data available (aka the I2PSession closed, etc)
* @throws ConnectException if the I2PServerSocket is closed
*/
public I2PSocket accept() throws I2PException;
public I2PSocket accept() throws I2PException, ConnectException;
/**
* Access the manager which is coordinating the server socket

View File

@ -1,5 +1,7 @@
package net.i2p.client.streaming;
import java.net.ConnectException;
import net.i2p.I2PException;
import net.i2p.util.Log;
@ -12,42 +14,61 @@ class I2PServerSocketImpl implements I2PServerSocket {
private I2PSocketManager mgr;
private I2PSocket cached = null; // buffer one socket here
private boolean closing = false; // Are we being closed?
private Object acceptLock = new Object();
public I2PServerSocketImpl(I2PSocketManager mgr) {
this.mgr = mgr;
}
public synchronized I2PSocket accept() throws I2PException {
while (cached == null) {
public synchronized I2PSocket accept() throws I2PException, ConnectException {
I2PSocket ret;
synchronized (acceptLock) {
while ((cached == null) && !closing) {
myWait();
}
I2PSocket ret = cached;
if (closing) {
throw new ConnectException("I2PServerSocket closed");
}
ret = cached;
cached = null;
notifyAll();
acceptLock.notifyAll();
}
_log.debug("TIMING: handed out accept result " + ret.hashCode());
return ret;
}
public synchronized boolean getNewSocket(I2PSocket s) {
public boolean getNewSocket(I2PSocket s) {
synchronized (acceptLock) {
while (cached != null) {
myWait();
}
cached = s;
notifyAll();
acceptLock.notifyAll();
}
return true;
}
public void close() throws I2PException {
//noop
}
private void myWait() {
try {
wait();
} catch (InterruptedException ex) {
synchronized (acceptLock) {
closing = true;
acceptLock.notifyAll();
}
}
public I2PSocketManager getManager() {
return mgr;
}
private void myWait() {
try {
acceptLock.wait();
} catch (InterruptedException ex) {}
}
}