code: public void dispatchEvent(final ManagerEvent event)
      {
          if (logger.isDebugEnabled())
          {
              logger.debug("dispatch=" + event.toString()); //$NON-NLS-1$
          }
  
          // take a copy of the listeners so they can be modified whilst we
          // iterate over them
          // The iteration may call some long running processes.
          final List<FilteredManagerListenerWrapper> listenerCopy;
          synchronized (this.listeners)
          {
              listenerCopy = this.listeners.getCopyAsList();
          }
  
          try
          {
              final LogTime totalTime = new LogTime();
  
              CountDownLatch latch = new CountDownLatch(listenerCopy.size());
  
              for (final FilteredManagerListenerWrapper filter : listenerCopy)
              {
                  if (filter.requiredEvents.contains(event.getClass()))
                  {
                      dispatchEventOnThread(event, filter, latch);
                  }
                  else
                  {
                      // this listener didn't want the event, so just decrease the
                      // countdown
                      latch.countDown();
                  }
              }
  
              latch.await();
  
              if (totalTime.timeTaken() > 500)
              {
                  logger.warn("Too long to process event " + event + " time taken: " + totalTime.timeTaken()); //$NON-NLS-1$ //$NON-NLS-2$
              }
          }
          catch (InterruptedException e)
          {
              Thread.interrupted();
          }
      }
docs: Events are sent here from the CoherentManagerEventQueue after being
  converted from a ManagerEvent to an ManagerEvent. This method is called
  from a dedicated thread attached to the event queue which it uses for
  dispatching events.