/** * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that * are part of this {@link ChannelGroup}, at the time of calling, are closed. */ public ChannelGroupFuture newCloseFuture(ChannelMatcher matcher) { Map<Channel, ChannelFuture> futures = new LinkedHashMap<Channel, ChannelFuture>(size()); for (Channel c : serverChannels) { if (matcher.matches(c)) { futures.put(c, c.closeFuture()); } } for (Channel c : nonServerChannels) { if (matcher.matches(c)) { futures.put(c, c.closeFuture()); } } return new DefaultChannelGroupFuture(this, futures, executor); }
@Override public boolean add(Channel channel) { ConcurrentSet<Channel> set = channel instanceof ServerChannel ? serverChannels : nonServerChannels; boolean added = set.add(channel); if (added) { channel.closeFuture().addListener(remover); } if (stayClosed && closed) { // First add channel, than check if closed. // Seems inefficient at first, but this way a volatile // gives us enough synchronization to be thread-safe. // // If true: Close right away. // (Might be closed a second time by ChannelGroup.close(), but this is ok) // // If false: Channel will definitely be closed by the ChannelGroup. // (Because closed=true always happens-before ChannelGroup.close()) // // See https://github.com/netty/netty/issues/4020 channel.close(); } return added; }
@Override public boolean remove(Object o) { if (!(o instanceof Channel)) { return false; } boolean removed; Channel c = (Channel) o; if (c instanceof ServerChannel) { removed = serverChannels.remove(c); } else { removed = nonServerChannels.remove(c); } if (!removed) { return false; } c.closeFuture().removeListener(remover); return true; }