/** {@inheritDoc} */
  @Override
  public <T> Future<T> broadcast(T msg, Set<AtmosphereResource<?, ?>> subset) {

    if (destroyed.get())
      throw new IllegalStateException("This Broadcaster has been destroyed and cannot be used");

    start();
    Object newMsg = filter(msg);
    if (newMsg == null) return null;

    BroadcasterFuture<Object> f = new BroadcasterFuture<Object>(newMsg);
    messages.offer(new Entry(newMsg, subset, f, msg));
    return f;
  }
  /** {@inheritDoc} */
  @Override
  public <T> Future<T> broadcastOnResume(T msg) {

    if (destroyed.get())
      throw new IllegalStateException("This Broadcaster has been destroyed and cannot be used");

    start();
    Object newMsg = filter(msg);
    if (newMsg == null) return null;

    BroadcasterFuture<Object> f = new BroadcasterFuture<Object>(newMsg);
    broadcastOnResume.offer(new Entry(newMsg, null, f, msg));
    return f;
  }
  /** {@inheritDoc} */
  public <T> Future<T> delayBroadcast(final T o, long delay, TimeUnit t) {

    if (destroyed.get())
      throw new IllegalStateException("This Broadcaster has been destroyed and cannot be used");

    start();
    final Object msg = filter(o);
    if (msg == null) return null;

    final BroadcasterFuture<Object> future = new BroadcasterFuture<Object>(msg);
    final Entry e = new Entry(msg, null, future, o);
    Future<T> f;
    if (delay > 0) {
      f =
          bc.getScheduledExecutorService()
              .schedule(
                  new Callable<T>() {

                    public T call() throws Exception {
                      delayedBroadcast.remove(e);
                      if (Callable.class.isAssignableFrom(o.getClass())) {
                        try {
                          Object r = Callable.class.cast(o).call();
                          final Object msg = filter(r);
                          if (msg != null) {
                            Entry entry = new Entry(msg, null, null, r);
                            push(entry);
                          }
                          return (T) msg;
                        } catch (Exception e1) {
                          logger.error("", e);
                        }
                      }

                      final Object msg = filter(o);
                      final Entry e = new Entry(msg, null, null, o);
                      push(e);
                      return (T) msg;
                    }
                  },
                  delay,
                  t);

      e.future = new BroadcasterFuture<Object>(f, msg);
    }
    delayedBroadcast.offer(e);
    return future;
  }
  /** {@inheritDoc} */
  public Future<?> scheduleFixedBroadcast(final Object o, long waitFor, long period, TimeUnit t) {

    if (destroyed.get())
      throw new IllegalStateException("This Broadcaster has been destroyed and cannot be used");

    start();
    if (period == 0 || t == null) {
      return null;
    }

    final Object msg = filter(o);
    if (msg == null) return null;

    return bc.getScheduledExecutorService()
        .scheduleWithFixedDelay(
            new Runnable() {
              public void run() {
                if (Callable.class.isAssignableFrom(o.getClass())) {
                  try {
                    Object r = Callable.class.cast(o).call();
                    final Object msg = filter(r);
                    if (msg != null) {
                      Entry entry = new Entry(msg, null, null, r);
                      push(entry);
                    }
                    return;
                  } catch (Exception e) {
                    logger.error("", e);
                  }
                }
                final Object msg = filter(o);
                final Entry e = new Entry(msg, null, null, o);
                push(e);
              }
            },
            waitFor,
            period,
            t);
  }