Permalink
Browse files

Merge pull request #21 from sonatype/stop-forking-guava-eventbus

REVIEW: Stop forking Guava event bus
  • Loading branch information...
2 parents 234a815 + 7276b2e commit b372b2003daf2896a06d0bdda455dc428cf1ec18 @adreghiciu adreghiciu committed Feb 25, 2014
@@ -11,13 +11,12 @@
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/
-package org.sonatype.sisu.goodies.eventbus.internal;
+package com.google.common.eventbus;
import javax.inject.Named;
import javax.inject.Singleton;
-import org.sonatype.sisu.goodies.eventbus.internal.guava.EventBus;
-import org.sonatype.sisu.goodies.eventbus.internal.guava.EventHandler;
+import org.sonatype.sisu.goodies.eventbus.internal.DefaultEventBus;
/**
* @since 1.5
@@ -29,7 +28,7 @@
{
@Override
- protected void dispatch(final Object event, final EventHandler wrapper) {
+ public void dispatch(final Object event, final EventSubscriber wrapper) {
DefaultEventBus.LOG.trace(DefaultEventBus.DISPATCHING, "Dispatching '{}' to {}", event, wrapper);
super.dispatch(event, wrapper);
}
@@ -11,18 +11,14 @@
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/
-package org.sonatype.sisu.goodies.eventbus.internal;
+package com.google.common.eventbus;
-import java.util.List;
+import java.util.LinkedList;
+import java.util.Queue;
import javax.inject.Named;
import javax.inject.Singleton;
-import org.sonatype.sisu.goodies.eventbus.internal.guava.EventBus;
-import org.sonatype.sisu.goodies.eventbus.internal.guava.EventHandler;
-
-import com.google.common.collect.Lists;
-
/**
* A Guava {@link EventBus} that differs from default one by dispatching events as they appear (is re-entrant).
* Guava will queue up all event and dispatch them in the order they were posted, without re-entrance.
@@ -36,26 +32,29 @@
{
/**
- * List of events for the current thread to dispatch
+ * Queues of events for the current thread to dispatch.
*/
- private final ThreadLocal<List<EventWithHandler>> eventsToDispatch = new ThreadLocal<List<EventWithHandler>>();
+ private final ThreadLocal<Queue<EventWithSubscriber>> eventsToDispatch =
+ new ThreadLocal<Queue<EventWithSubscriber>>()
+ {
+ @Override
+ protected Queue<EventWithSubscriber> initialValue() {
+ return new LinkedList<EventWithSubscriber>();
+ }
+ };
@Override
- protected void enqueueEvent(final Object event, final EventHandler handler) {
- if (eventsToDispatch.get() == null) {
- eventsToDispatch.set(Lists.<EventWithHandler>newArrayList());
- }
- eventsToDispatch.get().add(new EventWithHandler(event, handler));
+ void enqueueEvent(Object event, EventSubscriber subscriber) {
+ eventsToDispatch.get().offer(new EventWithSubscriber(event, subscriber));
}
@Override
- protected void dispatchQueuedEvents() {
- final List<EventWithHandler> eventWithHandlers = eventsToDispatch.get();
- if (eventWithHandlers != null) {
- eventsToDispatch.remove();
- for (final EventWithHandler eventWithHandler : eventWithHandlers) {
- dispatch(eventWithHandler.event, eventWithHandler.handler);
- }
+ void dispatchQueuedEvents() {
+ Queue<EventWithSubscriber> events = eventsToDispatch.get();
+ eventsToDispatch.remove();
+ EventWithSubscriber eventWithSubscriber;
+ while ((eventWithSubscriber = events.poll()) != null) {
+ dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber);
}
}
@@ -40,20 +40,16 @@
implements EventBus
{
- static final Logger LOG = LoggerFactory.getLogger(DefaultEventBus.class);
+ public static final Logger LOG = LoggerFactory.getLogger(DefaultEventBus.class);
private static final Marker REGISTRATION = MarkerFactory.getMarker("registration");
- private static final Marker EVENTS = MarkerFactory.getMarker("events");
+ public static final Marker DISPATCHING = MarkerFactory.getMarker("dispatching");
- static final Marker DISPATCHING = MarkerFactory.getMarker("dispatching");
-
- private final org.sonatype.sisu.goodies.eventbus.internal.guava.EventBus eventBus;
+ private final com.google.common.eventbus.EventBus eventBus;
@Inject
- public DefaultEventBus(final @Named("${guava.eventBus:-reentrant}")
- org.sonatype.sisu.goodies.eventbus.internal.guava.EventBus eventBus)
- {
+ public DefaultEventBus(final @Named("${guava.eventBus:-reentrant}") com.google.common.eventbus.EventBus eventBus) {
this.eventBus = checkNotNull(eventBus);
LOG.info("Using {}", eventBus);
}
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sonatype.sisu.goodies.eventbus.internal.guava;
-
-import java.lang.reflect.Method;
-import java.util.Set;
-
-import com.google.common.base.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Multimap;
-import com.google.common.eventbus.AllowConcurrentEvents;
-import com.google.common.eventbus.Subscribe;
-import com.google.common.reflect.TypeToken;
-import com.google.common.util.concurrent.UncheckedExecutionException;
-
-/**
- * A {@link HandlerFindingStrategy} for collecting all event handler methods that are marked with
- * the {@link Subscribe} annotation.
- *
- * @author Cliff Biffle
- * @author Louis Wasserman
- */
-class AnnotatedHandlerFinder
- implements HandlerFindingStrategy
-{
- /**
- * A thread-safe cache that contains the mapping from each class to all methods in that class and
- * all super-classes, that are annotated with {@code @Subscribe}. The cache is shared across all
- * instances of this class; this greatly improves performance if multiple EventBus instances are
- * created and objects of the same class are registered on all of them.
- */
- private static final LoadingCache<Class<?>, ImmutableList<Method>> handlerMethodsCache =
- CacheBuilder.newBuilder()
- .weakKeys()
- .build(new CacheLoader<Class<?>, ImmutableList<Method>>()
- {
- @Override
- public ImmutableList<Method> load(Class<?> concreteClass) throws Exception {
- return getAnnotatedMethodsInternal(concreteClass);
- }
- });
-
- /**
- * {@inheritDoc}
- *
- * This implementation finds all methods marked with a {@link Subscribe} annotation.
- */
- @Override
- public Multimap<Class<?>, EventHandler> findAllHandlers(Object listener) {
- Multimap<Class<?>, EventHandler> methodsInListener = HashMultimap.create();
- Class<?> clazz = listener.getClass();
- for (Method method : getAnnotatedMethods(clazz)) {
- Class<?>[] parameterTypes = method.getParameterTypes();
- Class<?> eventType = parameterTypes[0];
- EventHandler handler = makeHandler(listener, method);
- methodsInListener.put(eventType, handler);
- }
- return methodsInListener;
- }
-
- private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
- try {
- return handlerMethodsCache.getUnchecked(clazz);
- }
- catch (UncheckedExecutionException e) {
- throw Throwables.propagate(e.getCause());
- }
- }
-
- private static ImmutableList<Method> getAnnotatedMethodsInternal(Class<?> clazz) {
- Set<? extends Class<?>> supers = TypeToken.of(clazz).getTypes().rawTypes();
- ImmutableList.Builder<Method> result = ImmutableList.builder();
- for (Method method : clazz.getMethods()) {
- /*
- * Iterate over each distinct method of {@code clazz}, checking if it is annotated with
- * @Subscribe by any of the superclasses or superinterfaces that declare it.
- */
- for (Class<?> c : supers) {
- try {
- Method m = c.getMethod(method.getName(), method.getParameterTypes());
- if (m.isAnnotationPresent(Subscribe.class)) {
- Class<?>[] parameterTypes = method.getParameterTypes();
- if (parameterTypes.length != 1) {
- throw new IllegalArgumentException("Method " + method
- + " has @Subscribe annotation, but requires " + parameterTypes.length
- + " arguments. Event handler methods must require a single argument.");
- }
- Class<?> eventType = parameterTypes[0];
- result.add(method);
- break;
- }
- }
- catch (NoSuchMethodException ignored) {
- // Move on.
- }
- }
- }
- return result.build();
- }
-
- /**
- * Creates an {@code EventHandler} for subsequently calling {@code method} on
- * {@code listener}.
- * Selects an EventHandler implementation based on the annotations on
- * {@code method}.
- *
- * @param listener object bearing the event handler method.
- * @param method the event handler method to wrap in an EventHandler.
- * @return an EventHandler that will call {@code method} on {@code listener}
- * when invoked.
- */
- private static EventHandler makeHandler(Object listener, Method method) {
- EventHandler wrapper;
- if (methodIsDeclaredThreadSafe(method)) {
- wrapper = new EventHandler(listener, method);
- }
- else {
- wrapper = new SynchronizedEventHandler(listener, method);
- }
- return wrapper;
- }
-
- /**
- * Checks whether {@code method} is thread-safe, as indicated by the
- * {@link AllowConcurrentEvents} annotation.
- *
- * @param method handler method to check.
- * @return {@code true} if {@code handler} is marked as thread-safe,
- * {@code false} otherwise.
- */
- private static boolean methodIsDeclaredThreadSafe(Method method) {
- return method.getAnnotation(AllowConcurrentEvents.class) != null;
- }
-}
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2007 The Guava Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sonatype.sisu.goodies.eventbus.internal.guava;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.Executor;
-
-import com.google.common.annotations.Beta;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * An {@link EventBus} that takes the Executor of your choice and uses it to
- * dispatch events, allowing dispatch to occur asynchronously.
- *
- * @author Cliff Biffle
- * @since 10.0
- */
-@Beta
-public class AsyncEventBus
- extends EventBus
-{
- private final Executor executor;
-
- /**
- * the queue of events is shared across all threads
- */
- private final ConcurrentLinkedQueue<EventWithHandler> eventsToDispatch =
- new ConcurrentLinkedQueue<EventWithHandler>();
-
- /**
- * Creates a new AsyncEventBus that will use {@code executor} to dispatch
- * events. Assigns {@code identifier} as the bus's name for logging purposes.
- *
- * @param identifier short name for the bus, for logging purposes.
- * @param executor Executor to use to dispatch events. It is the caller's
- * responsibility to shut down the executor after the last event has
- * been posted to this event bus.
- */
- public AsyncEventBus(String identifier, Executor executor) {
- super(identifier);
- this.executor = checkNotNull(executor);
- }
-
- /**
- * Creates a new AsyncEventBus that will use {@code executor} to dispatch
- * events.
- *
- * @param executor Executor to use to dispatch events. It is the caller's
- * responsibility to shut down the executor after the last event has
- * been posted to this event bus.
- */
- public AsyncEventBus(Executor executor) {
- this.executor = checkNotNull(executor);
- }
-
- @Override
- protected void enqueueEvent(Object event, EventHandler handler) {
- eventsToDispatch.offer(new EventWithHandler(event, handler));
- }
-
- /**
- * Dispatch {@code events} in the order they were posted, regardless of
- * the posting thread.
- */
- @SuppressWarnings("deprecation") // only deprecated for external subclasses
- @Override
- protected void dispatchQueuedEvents() {
- while (true) {
- EventWithHandler eventWithHandler = eventsToDispatch.poll();
- if (eventWithHandler == null) {
- break;
- }
-
- dispatch(eventWithHandler.event, eventWithHandler.handler);
- }
- }
-
- /**
- * Calls the {@link #executor} to dispatch {@code event} to {@code handler}.
- */
- @Override
- protected void dispatch(final Object event, final EventHandler handler) {
- checkNotNull(event);
- checkNotNull(handler);
- executor.execute(
- new Runnable()
- {
- @Override
- public void run() {
- AsyncEventBus.super.dispatch(event, handler);
- }
- });
- }
-}
Oops, something went wrong.

0 comments on commit b372b20

Please sign in to comment.