@SuppressWarnings("unchecked") private <E extends Event> void doPost(E e) { ListenerBucket<E> b; Listener<? super E>[] ls = null; Lock l = locks.get(e); l.lock(); try { if (retained) { if ((b = (ListenerBucket<E>) handlers.get(e)) == null) handlers.put(e, b = (ListenerBucket<E>) bucketSupplier.get()); ls = b.post(e); } else { if ((b = (ListenerBucket<E>) handlers.get(e)) != null) { ls = b.post(e); if (b.isEmpty()) handlers.remove(e); } } } finally { l.unlock(); } if (ls != null) { for (Listener<? super E> li : ls) { try { li.execute(e); } catch (RejectedExecutionException ex) { Log.get().postSevere("Event listener rejected! Did the executor shut down?", ex); } } } }
/** * Registers the specified event listener. * * @param e The event to listen for. * @param l The event listener. * @throws NullPointerException if either argument is null. */ protected final <E extends Event> void doAddListener(E e, Listener<? super E> li) { Objects.requireNonNull(li); Lock l = locks.get(e); l.lock(); try { if (handlers.computeIfAbsent(e, k -> bucketSupplier.get()).addListener(li)) return; } finally { l.unlock(); } // No return = listener rejected = we should execute it now li.execute(e); }
/** * Removes an event listener, if it exists. * * <p>Note that this method generally does not interact nicely with lambdas as they aren't * designed for equality testing. As such, when using this method, ensure you're properly * unregistering a listener! * * @param e The event being listened for. * @param handler The handler to remove. * @throws NullPointerException if either argument is null. */ public <E extends Event> void removeListener(E e, EventHandler<? super E> handler) { Objects.requireNonNull(handler); Lock l = locks.get(e); l.lock(); try { ListenerBucket<?> b = handlers.get(e); if (b != null) { b.removeListener(li -> li.handler.equals(handler)); if (b.isEmpty()) handlers.remove(e); } } finally { l.unlock(); } }
/** * Clears any listeners satisfying the specified predicate. This is exposed for subclasses to * utilise if they wish; however it is not a part of the public API for obvious reasons. * * @throws NullPointerException if {@code pred} is {@code null}. */ public final void clearListeners(Predicate<Listener<?>> pred) { Objects.requireNonNull(pred); handlers .entrySet() .removeIf( e -> { Lock l = locks.get(e.getKey()); l.lock(); try { ListenerBucket<?> b = e.getValue(); b.removeListeners(pred); return b.isEmpty(); } finally { l.unlock(); } }); }