/**
   * 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;
  }