package com.google.common.eventbus; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.Queue; import java.util.Set; import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.Logger; import com.google.common.eventbus.EventBus.LoggingHandler; /** * An {@link EventBus} that mix synchronous event dispatching of {@link EventBus} and asynchronous of {@link AsyncEventBus} * * In case of synchronous dispatching this is the calling thread that executes the dispatching otherwise it is the specified executor * * @author Nicolas Gaud * */ public class AsyncSyncEventBus extends EventBus { private Dispatcher syncDispatcher = Dispatcher.perThreadDispatchQueue(); public AsyncSyncEventBus(String identifier, Executor executor, Class<? extends Annotation> annotation) { super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE,annotation); } public AsyncSyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler, Class<? extends Annotation> annotation) { super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler,annotation); } public AsyncSyncEventBus(Executor executor, Class<? extends Annotation> annotation) { super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE,annotation); } public void fire(Object event) { Iterator<Subscriber> eventSubscribers = getSubscribers().getSubscribers(event); if (eventSubscribers.hasNext()) { this.syncDispatcher.dispatch(event, eventSubscribers); } else if (!(event instanceof DeadEvent)) { // the event had no subscribers and was not itself a DeadEvent this.fire(new DeadEvent(this, event)); } } /* * public AsyncSyncEventBus(String identifier, Executor executor) { super(identifier, executor); } * * public AsyncSyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) { super(executor, subscriberExceptionHandler); } * * public AsyncSyncEventBus(Executor executor) { super(executor); * * } * * public void fire(Object event) { Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass()); * * boolean dispatched = false; for (Class<?> eventType : dispatchTypes) { subscribersByTypeLock.readLock().lock(); try { Set<EventSubscriber> wrappers = subscribersByType .get(eventType); * * if (!wrappers.isEmpty()) { dispatched = true; for (EventSubscriber wrapper : wrappers) { eventsToDispatch.get().offer(new EventWithSubscriber(event, wrapper)); } } } finally { subscribersByTypeLock.readLock().unlock(); } } * * if (!dispatched && !(event instanceof DeadEvent)) { fire(new DeadEvent(this, event)); } * * fireQueuedEvents(); } * * void fireQueuedEvents() { // don't dispatch if we're already dispatching, that would allow // reentrancy // and out-of-order events. Instead, leave the events to be dispatched // after the in-progress dispatch is complete. if (isDispatching.get()) { return; } * * isDispatching.set(true); try { Queue<EventWithSubscriber> events = eventsToDispatch.get(); EventWithSubscriber eventWithSubscriber; while ((eventWithSubscriber = events.poll()) != null) { synchronousDispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber); } } finally { isDispatching.remove(); eventsToDispatch.remove(); } } * * void synchronousDispatch(Object event, EventSubscriber wrapper) { try { wrapper.handleEvent(event); } catch (InvocationTargetException e) { try { subscriberExceptionHandler.handleException( e.getCause(), new SubscriberExceptionContext(this, event, wrapper .getSubscriber(), wrapper.getMethod())); } catch (Throwable t) { // If the exception handler throws, log it. There isn't much // else to do! Logger.getLogger(AsyncSyncEventBus.class.getName()) .log(Level.SEVERE, String.format( "Exception %s thrown while handling exception: %s", t, e.getCause()), t); } } } */ }