
zmq.Signaler Maven / Gradle / Ivy
package zmq;
import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.Pipe;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.concurrent.atomic.AtomicLong;
import zmq.util.Errno;
import zmq.util.Utils;
// This is a cross-platform equivalent to signal_fd. However, as opposed
// to signal_fd there can be at most one signal in the signaler at any
// given moment. Attempt to send a signal before receiving the previous
// one will result in undefined behaviour.
final class Signaler implements Closeable
{
private interface IoOperation
{
O call() throws IOException;
}
// Underlying write & read file descriptor.
private final Pipe.SinkChannel w;
private final Pipe.SourceChannel r;
private final Selector selector;
private final ThreadLocal wdummy = ThreadLocal.withInitial(() -> ByteBuffer.allocate(1));
private final ThreadLocal rdummy = ThreadLocal.withInitial(() -> ByteBuffer.allocate(1));
// Selector.selectNow at every sending message doesn't show enough performance
private final AtomicLong wcursor = new AtomicLong(0);
private long rcursor = 0;
private final Errno errno;
private final int pid;
private final Ctx ctx;
Signaler(Ctx ctx, int pid, Errno errno)
{
this.ctx = ctx;
this.pid = pid;
this.errno = errno;
// Create the socket pair for signaling.
try {
Pipe pipe = Pipe.open();
r = pipe.source();
w = pipe.sink();
// Set both fds to non-blocking mode.
Utils.unblockSocket(w, r);
selector = ctx.createSelector();
r.register(selector, SelectionKey.OP_READ);
}
catch (IOException e) {
throw new ZError.IOException(e);
}
}
private O maksInterrupt(IoOperation operation) throws IOException
{
// This loop try to protect the current thread from external interruption.
// If it happens, it mangles current context internal state.
// So it keep trying until it succeed.
// This must only be called on internal IO (using Pipe)
boolean interrupted = Thread.interrupted();
while (true) {
try {
return operation.call();
}
catch (ClosedByInterruptException e) {
interrupted = true;
}
finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
}
@Override
public void close() throws IOException
{
IOException exception = null;
IoOperation
© 2015 - 2025 Weber Informatics LLC | Privacy Policy