/** * Returns all the Listeners to a topic. * * <p>The registry is NOT thread-safe, and so this can only be called from within the actor * mailbox context. */ @Override public final List<TActor> listenersFor(final Object topic) { Preconditions.checkNotNull(topic, "topic cannot be null"); if (listeners != null) { final List<Object> list = listeners.get(topic); if (list != null) { final List<TActor> result = new ArrayList<>(list.size()); boolean processQueue = false; for (final Object obj : list) { if (obj instanceof WeakReferenceWithTopic) { final WeakReferenceWithTopic ref = (WeakReferenceWithTopic) obj; final TActor actor = ref.get(); if (actor == null) { processQueue = true; } else { result.add(actor); } } else { final TActor actor = (TActor) obj; result.add(actor); } } if (processQueue) { processWeakListenerQueue(); } return result; } } return Collections.emptyList(); }
/** * Registers a listener actor. * * <p>The registry is NOT thread-safe, and so this can only be called from within the actor * mailbox context. * * <p>The topic might be anything, but should be immutable. Remember that the registry is also * used by base classes and derived classes. The topic cannot be null. The listener cannot be * null. The listener must not already have been registered to this topic. */ @Override public final void register(final Object topic, final TActor listener, final boolean weakRef) { Preconditions.checkNotNull(topic, "topic cannot be null"); Preconditions.checkNotNull(listener, "listener cannot be null"); if (listeners == null) { listeners = new HashMap<Object, List<Object>>(); } List<Object> list = listeners.get(topic); if (list == null) { list = new ArrayList<Object>(); listeners.put(topic, list); } for (final Object obj : list) { if (obj == listener) { throw new IllegalStateException( "listener " + listener + " already registered for topic " + topic); } else if (obj instanceof WeakReferenceWithTopic) { final WeakReferenceWithTopic ref = (WeakReferenceWithTopic) obj; if (ref.get() == listener) { throw new IllegalStateException( "listener " + listener + " already registered for topic " + topic); } } } if (weakRef) { if (refQueue == null) { refQueue = new ReferenceQueue<Object>(); } list.add(new WeakReferenceWithTopic(topic, listener, refQueue)); } else { list.add(listener); } }
/** * Unregisters a listener actor. * * <p>The registry is NOT thread-safe, and so this can only be called from within the actor * mailbox context. * * @return true on success. */ @Override public final boolean unregister(final Object topic, final TActor listener) { Preconditions.checkNotNull(topic, "topic cannot be null"); Preconditions.checkNotNull(listener, "listener cannot be null"); if (listeners != null) { final List<Object> list = listeners.get(topic); if (list != null) { final int size = list.size(); for (int i = 0; i < size; i++) { final Object obj = list.get(i); if (obj == listener) { if (list.size() == 1) { listeners.remove(topic); } else { list.remove(i); } return true; } else if (obj instanceof WeakReferenceWithTopic) { final WeakReferenceWithTopic ref = (WeakReferenceWithTopic) obj; if (ref.get() == listener) { if (list.size() == 1) { listeners.remove(topic); } else { list.remove(i); } return true; } } } } } return false; }