_multiCast = true;
try {
_address = InetAddress.getByName(_defaultReturnAddress);
} catch (UnknownHostException ex) {
throw new IllegalActionException(this, ex,
"The default remote "
+ "address specifies an unknown host");
}
if (_multicastSocket != null) {
try {
_multicastSocket.joinGroup(_address);
} catch (IOException exp) {
throw new IllegalActionException(
"can't join the multicast group" + exp);
}
}
} else {
//FIXME: what should it do when change from multicast to unicast...
_multiCast = false;
if (_multicastSocket != null) {
try {
_multicastSocket.leaveGroup(_address);
} catch (IOException exp) {
throw new IllegalActionException(this, exp,
"Disconnecting from the multicast group "
+ "failed.");
}
}
}
}
} else if (attribute == defaultReturnSocketNumber) {
synchronized (_syncDefaultOutputs) {
_defaultReturnSocketNumber = ((IntToken) defaultReturnSocketNumber
.getToken()).intValue();
}
} else if (attribute == defaultOutput) {
synchronized (_syncDefaultOutputs) {
_defaultOutputToken = output.getType().convert(
defaultOutput.getToken());
}
// In the case of <i>blockAwaitingDatagram</i> or <i>overwrite</i>,
// notify potentially waiting fire() or thread respectively
// that it might no longer need to wait. Each will recheck its
// conditions when notified, so extra notifications merely
// waste a little CPU.
} else if (attribute == overwrite) {
_overwrite = ((BooleanToken) (overwrite.getToken())).booleanValue();
if (_overwrite) {
synchronized (_syncFireAndThread) {
_syncFireAndThread.notifyAll();
}
}
} else if (attribute == blockAwaitingDatagram) {
_blockAwaitingDatagram = ((BooleanToken) (blockAwaitingDatagram
.getToken())).booleanValue();
if (!_blockAwaitingDatagram) {
synchronized (_syncFireAndThread) {
_syncFireAndThread.notifyAll();
}
}
// In the case of <i>localSocketNumber</i> it is necessary to
// disturb the thread if it is in the call to
// socket.receive(). This is rather disruptive, so I choose
// to act on these attribute change requests only if the value
// of this parameter has actually changed. Furthermore, when
// receive() is busy, wait 444mS (an arbitrary choice) to
// see if receive will return on its own. Close and
// re-create the socket when either the time expires or
// the receive() call returns, whichever comes first.
//
// Point of interest: The behavior of a datagram socket
// upon close() by one thread while another thread is
// stalled in receive() on the same socket is given in
// page 3 of file:///D%7C/Depot/j2sdk-1_3_1-doc/
// docs/guide/misc/threadPrimitiveDeprecation.html
// "What if a thread doesn't respond to Thread.interrupt?"
} else if (attribute == localSocketNumber) {
// FIXME-- Try again w/o sync(this):
// Unlike other attributes, concurrent calls here
// (each with attribute == localSocketNumber have
// caused an exception to be thrown. (Or, was it that
// socket so recently closed had not fully released
// that socket number!)
// Note: This synchronized block breaks codegen.
synchronized (this) {
if (_multiCast == true) {
}
if ((_socket != null) || (_multicastSocket != null)) {
// Verify presence & health of the thread.
if (_socketReadingThread == null) {
throw new IllegalActionException(this, "thread == null");
} else if (!_socketReadingThread.isAlive()) {
throw new IllegalActionException(this,
"thread is not Alive");
}
int newSocketNumber = ((IntToken) (localSocketNumber
.getToken())).intValue();
if ((_multicastSocket != null)
&& (newSocketNumber != _multicastSocket
.getLocalPort())) {
synchronized (_syncSocket) {
if (_inReceive) {
// Wait for receive to finish, if it
// does not take very long that is.
try {
_syncSocket.wait(444);
} catch (InterruptedException ex) {
throw new IllegalActionException(this, ex,
"Interrupted while waiting");
}
// Either I've been notified that receive()
// has completed, or the timeout has occurred.
// It does not matter which. Either way I am
// now ready to close and re-open the socket.
}
_multicastSocket.close();
try {
_multicastSocket = new MulticastSocket(
newSocketNumber);
} catch (Exception ex) {
throw new InternalErrorException(this, ex,
"Couldn't open new socket number "
+ newSocketNumber);
}
if (_address != null) {
try {
_multicastSocket.joinGroup(_address);
} catch (IOException exp) {
throw new IllegalActionException(
"can't join the multicast group"
+ exp);
}
}
}
} else if ((_socket != null)
&& (newSocketNumber != _socket.getLocalPort())) {
synchronized (_syncSocket) {
if (_inReceive) {
// Wait for receive to finish, if it
// does not take very long that is.
try {
_syncSocket.wait(444);
} catch (InterruptedException ex) {
throw new IllegalActionException(this, ex,
"Interrupted while waiting");
}
// Either I've been notified that receive()
// has completed, or the timeout has occurred.