package edu.uw.zookeeper.net.intravm; import java.util.Iterator; import java.util.Queue; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executor; import org.apache.logging.log4j.Logger; import com.google.common.collect.ImmutableList; import com.google.common.collect.Queues; import com.google.common.collect.Sets; import edu.uw.zookeeper.common.Actors; import edu.uw.zookeeper.common.Automaton; import edu.uw.zookeeper.common.Eventful; import edu.uw.zookeeper.net.Connection; /** * Queues events when there are no listeners */ public class IntraVmPublisher<O> extends Actors.ExecutedPeekingQueuedActor<Object> implements Eventful<Connection.Listener<? super O>> { public static <O> IntraVmPublisher<O> defaults(Executor executor, Logger logger) { return new IntraVmPublisher<O>( ImmutableList.<Connection.Listener<? super O>>of(), executor, Queues.<Object>newConcurrentLinkedQueue(), logger); } protected final CopyOnWriteArraySet<Connection.Listener<? super O>> listeners; protected IntraVmPublisher( Iterable<Connection.Listener<? super O>> listeners, Executor executor, Queue<Object> mailbox, Logger logger) { super(executor, mailbox, logger); this.listeners = Sets.newCopyOnWriteArraySet(listeners); } @Override public boolean isReady() { return (!listeners.isEmpty() && !mailbox.isEmpty()); } @Override public void subscribe(Connection.Listener<? super O> listener) { listeners.add(listener); run(); } @Override public boolean unsubscribe(Connection.Listener<? super O> listener) { return listeners.remove(listener); } @SuppressWarnings("unchecked") @Override protected boolean apply(Object input) throws Exception { Iterator<Connection.Listener<? super O>> itr = listeners.iterator(); boolean success = itr.hasNext() && mailbox.remove(input); if (input instanceof Automaton.Transition) { Automaton.Transition<Connection.State> state = (Automaton.Transition<Connection.State>) input; while (success && itr.hasNext()) { itr.next().handleConnectionState(state); } if (state.to() == Connection.State.CONNECTION_CLOSED) { stop(); } } else { O message = (O) input; while (success && itr.hasNext()) { itr.next().handleConnectionRead(message); } } return success; } @Override protected void doStop() { mailbox.clear(); listeners.clear(); } }