docs: private <Q extends T> Q dispatch(final Q event, boolean stopOnFirstException) {
  
  		if (event == null) {
  			throw new IllegalArgumentException("event is null");
  		}
  
  		if (this.baseClass != null && !this.baseClass.isAssignableFrom(event.getClass())) {
  			throw new IllegalArgumentException("event of type " + event.getClass().getName()
  					+ " not dispatchable over this event scope of base type '" + this.baseClass.getName() + "'");
  		}
  
  		final Collection<ReceiverDescriptor> receivers = new TreeSet<ReceiverDescriptor>(new DispatchComparator());
  
  		this.collectReceiver(event.getClass(), receivers);
  
  		// no receivers registered, so bye-bye
  		if (receivers == null || receivers.size() < 1) {
  			return event;
  		}
  
  		// when finding a garbage collected receiver, store here
  		final List<ReceiverDescriptor> defunct = new LinkedList<ReceiverDescriptor>();
  
  		try {
  			for (final ReceiverDescriptor receiverDescriptor : receivers) {
  				final Object receiver = receiverDescriptor.receiverReference.get();
  				if (receiver == null) {
  
  					defunct.add(receiverDescriptor);
  					continue;
  				}
  				try {
  					receiverDescriptor.method.setAccessible(true);
  					receiverDescriptor.method.invoke(receiver, event);
  				} catch (final Exception e) {
  					if (stopOnFirstException) {
  
  						// wrap non runtime exception and throw up
  						throw new DispatchException(receiver, event, e);
  					}
  				}
  			}
  		} finally {
  			// throw away gc'ed items
  			receivers.removeAll(defunct);
  		}
  		return event;
  	}