/**
   * Create a {@link ScheduledExecutorService} used ot schedule I/O and non I/O events.
   *
   * @param config the {@link AtmosphereConfig}
   * @return {@link ScheduledExecutorService}
   */
  public static ScheduledExecutorService getScheduler(final AtmosphereConfig config) {
    final boolean shared = config.framework().isShareExecutorServices();

    if (!shared || config.properties().get("scheduler") == null) {
      ScheduledExecutorService scheduler =
          Executors.newScheduledThreadPool(
              Runtime.getRuntime().availableProcessors(),
              new ThreadFactory() {

                private final AtomicInteger count = new AtomicInteger();

                @Override
                public Thread newThread(final Runnable runnable) {
                  Thread t =
                      new Thread(runnable, "Atmosphere-Scheduler-" + count.getAndIncrement());
                  t.setDaemon(true);
                  return t;
                }
              });

      if (shared) {
        config.properties().put("scheduler", scheduler);
      }
      return scheduler;
    } else {
      return (ScheduledExecutorService) config.properties().get("scheduler");
    }
  }
 /** {@inheritDoc} */
 @Override
 protected BroadcasterConfig createBroadcasterConfig(AtmosphereConfig config) {
   BroadcasterConfig bc =
       (BroadcasterConfig) config.properties().get(BroadcasterConfig.class.getName());
   if (bc == null) {
     bc = new BroadcasterConfig(config.framework().broadcasterFilters(), config, false, getID());
     config.properties().put(BroadcasterConfig.class.getName(), bc);
   }
   return bc;
 }
  @Override
  public void configure(AtmosphereConfig config) {
    Object o = config.properties().get("shared");
    if (o != null) {
      isShared = Boolean.parseBoolean(o.toString());
    }

    if (isShared) {
      reaper = ExecutorsFactory.getScheduler(config);
    } else {
      reaper = Executors.newSingleThreadScheduledExecutor();
    }
    this.config = config;
  }
  /**
   * Create an {@link ExecutorService} to be used for dispatching messages, not I/O events.
   *
   * @param config the {@link AtmosphereConfig}
   * @param name a name to use if shared is false.
   * @return {@link ExecutorService}
   */
  public static ExecutorService getMessageDispatcher(
      final AtmosphereConfig config, final String name) {
    final boolean shared = config.framework().isShareExecutorServices();

    boolean isExecutorShared = shared ? true : false;
    if (!shared || config.properties().get("executorService") == null) {
      int numberOfMessageProcessingThread = DEFAULT_MESSAGE_THREAD;
      String s =
          config.getInitParameter(
              ApplicationConfig.BROADCASTER_MESSAGE_PROCESSING_THREADPOOL_MAXSIZE);
      if (s != null) {
        numberOfMessageProcessingThread = Integer.parseInt(s);
      }

      if (isExecutorShared && numberOfMessageProcessingThread == 1) {
        logger.warn(
            "Not enough numberOfMessageProcessingThread for a shareable thread pool {}, "
                + "Setting it to a newCachedThreadPool",
            numberOfMessageProcessingThread);
        numberOfMessageProcessingThread = -1;
      }

      ThreadPoolExecutor messageService;
      if (numberOfMessageProcessingThread == -1) {
        messageService =
            (ThreadPoolExecutor)
                Executors.newCachedThreadPool(
                    new ThreadFactory() {

                      private final AtomicInteger count = new AtomicInteger();

                      @Override
                      public Thread newThread(final Runnable runnable) {
                        Thread t =
                            new Thread(
                                runnable,
                                (shared ? "Atmosphere-Shared" : name)
                                    + "-DispatchOp-"
                                    + count.getAndIncrement());
                        t.setDaemon(true);
                        return t;
                      }
                    });
      } else {
        messageService =
            (ThreadPoolExecutor)
                Executors.newFixedThreadPool(
                    numberOfMessageProcessingThread,
                    new ThreadFactory() {

                      private final AtomicInteger count = new AtomicInteger();

                      @Override
                      public Thread newThread(final Runnable runnable) {
                        Thread t =
                            new Thread(
                                runnable,
                                (shared ? "Atmosphere-Shared" : name)
                                    + "-DispatchOp-"
                                    + count.getAndIncrement());
                        t.setDaemon(true);
                        return t;
                      }
                    });
      }

      keepAliveThreads(messageService, config);

      if (shared) {
        config.properties().put("executorService", messageService);
      }
      return messageService;
    } else {
      return (ExecutorService) config.properties().get("executorService");
    }
  }