@Override
 public void run(Timeout timeout) throws Exception {
   if (timeout.isCancelled()) {
     return;
   }
   if (lifecycle.stoppedOrClosed()) {
     listener.onClose();
   } else {
     listener.onTimeout(this.timeout);
   }
   // note, we rely on the listener to remove itself in case of timeout if needed
 }
 public void add(TimeValue timeout, final TimeoutClusterStateListener listener) {
   if (lifecycle.stoppedOrClosed()) {
     listener.onClose();
     return;
   }
   NotifyTimeout notifyTimeout = new NotifyTimeout(listener, timeout);
   Timeout timerTimeout =
       timerService.newTimeout(notifyTimeout, timeout, TimerService.ExecutionType.THREADED);
   onGoingTimeouts.add(new Tuple<Timeout, NotifyTimeout>(timerTimeout, notifyTimeout));
   clusterStateListeners.add(listener);
   // call the post added notification on the same event thread
   updateTasksExecutor.execute(
       new Runnable() {
         @Override
         public void run() {
           listener.postAdded();
         }
       });
 }