#2576: Allow plugins to register multiple intents for async events

This commit is contained in:
Virizion 2019-01-07 01:40:48 -05:00 committed by md_5
parent 9a2acc826e
commit 8b5a89bf12

View File

@ -1,8 +1,7 @@
package net.md_5.bungee.api.event; package net.md_5.bungee.api.event;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.Collections; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -25,7 +24,7 @@ public class AsyncEvent<T> extends Event
{ {
private final Callback<T> done; private final Callback<T> done;
private final Set<Plugin> intents = Collections.newSetFromMap( new ConcurrentHashMap<Plugin, Boolean>() ); private final Map<Plugin, AtomicInteger> intents = new ConcurrentHashMap<Plugin, AtomicInteger>();
private final AtomicBoolean fired = new AtomicBoolean(); private final AtomicBoolean fired = new AtomicBoolean();
private final AtomicInteger latch = new AtomicInteger(); private final AtomicInteger latch = new AtomicInteger();
@ -43,30 +42,40 @@ public class AsyncEvent<T> extends Event
/** /**
* Register an intent that this plugin will continue to perform work on a * Register an intent that this plugin will continue to perform work on a
* background task, and wishes to let the event proceed once the registered * background task, and wishes to let the event proceed once the registered
* background task has completed. * background task has completed. Multiple intents can be registered by a
* plugin, but the plugin must complete the same amount of intents for the
* event to proceed.
* *
* @param plugin the plugin registering this intent * @param plugin the plugin registering this intent
*/ */
public void registerIntent(Plugin plugin) public void registerIntent(Plugin plugin)
{ {
Preconditions.checkState( !fired.get(), "Event %s has already been fired", this ); Preconditions.checkState( !fired.get(), "Event %s has already been fired", this );
Preconditions.checkState( !intents.contains( plugin ), "Plugin %s already registered intent for event %s", plugin, this );
intents.add( plugin ); AtomicInteger intentCount = intents.get( plugin );
if ( intentCount == null )
{
intents.put( plugin, new AtomicInteger( 1 ) );
} else
{
intentCount.incrementAndGet();
}
latch.incrementAndGet(); latch.incrementAndGet();
} }
/** /**
* Notifies this event that this plugin has done all its required processing * Notifies this event that this plugin has completed an intent and wishes
* and wishes to let the event proceed. * to let the event proceed once all intents have been completed.
* *
* @param plugin a plugin which has an intent registered for this event * @param plugin a plugin which has an intent registered for this event
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void completeIntent(Plugin plugin) public void completeIntent(Plugin plugin)
{ {
Preconditions.checkState( intents.contains( plugin ), "Plugin %s has not registered intent for event %s", plugin, this ); AtomicInteger intentCount = intents.get( plugin );
intents.remove( plugin ); Preconditions.checkState( intentCount != null && intentCount.get() > 0, "Plugin %s has not registered intents for event %s", plugin, this );
intentCount.decrementAndGet();
if ( fired.get() ) if ( fired.get() )
{ {
if ( latch.decrementAndGet() == 0 ) if ( latch.decrementAndGet() == 0 )