ferrybig

MainThreadPlanner.java - a class designed for Bukkit progra.

Jul 27th, 2014
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.73 KB | None | 0 0
  1. package sander;
  2.  
  3. import java.util.ArrayList;
  4. import static java.util.Collections.addAll;
  5. import java.util.List;
  6. import static org.bukkit.Bukkit.getScheduler;
  7. import org.bukkit.plugin.Plugin;
  8.  
  9. public class MainThreadPlanner<T> {
  10.  
  11.     private AccumulativeRunnable<T> doProcess;
  12.     private final AccumulativeRunnable<Runnable> doSubmit;
  13.     protected final Plugin plugin;
  14.     private final Processor<T> processor;
  15.  
  16.     public MainThreadPlanner(Plugin plugin,Processor<T> processor) {
  17.         this.doSubmit = new DoSubmitAccumulativeRunnable(plugin);
  18.         this.plugin = plugin;
  19.         this.processor = processor;
  20.     }
  21.  
  22.     private void process(List<T> chunks) {
  23.         this.processor.process(chunks);
  24.     }
  25.  
  26.     /**
  27.      * Sends data chunks to the {@link #process} method. This method is to be
  28.      * used from inside the {@code doInBackground} method to deliver
  29.      * intermediate results for processing on the <i>Bukkit Main Server
  30.      * Thread</i> inside the {@code process} method.
  31.      *
  32.      * <p>
  33.      * Because the {@code process} method is invoked asynchronously on the
  34.      * <i>Bukkit Main Server Thread</i>
  35.      * multiple invocations to the {@code publish} method might occur before the
  36.      * {@code process} method is executed. For performance purposes all these
  37.      * invocations are coalesced into one invocation with concatenated
  38.      * arguments.
  39.      *
  40.      * <p>
  41.      * For example:
  42.      *
  43.      * <pre>
  44.      * publish(&quot;1&quot;);
  45.      * publish(&quot;2&quot;, &quot;3&quot;);
  46.      * publish(&quot;4&quot;, &quot;5&quot;, &quot;6&quot;);
  47.      * </pre>
  48.      *
  49.      * might result in:
  50.      *
  51.      * <pre>
  52.      * process(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;)
  53.      * </pre>
  54.      *
  55.      *
  56.      * @param chunks intermediate results to process
  57.      *
  58.      * @see #process
  59.      *
  60.      */
  61.     public final void publish(T... chunks) {
  62.         synchronized (this) {
  63.             if (this.doProcess == null) {
  64.                 this.doProcess = new AccumulativeRunnable<T>() {
  65.                     @Override
  66.                     public void run(List<T> args) {
  67.                         MainThreadPlanner.this.process(args);
  68.                     }
  69.  
  70.                     @Override
  71.                     protected void submit() {
  72.                         MainThreadPlanner.this.doSubmit.add(this);
  73.                     }
  74.                 };
  75.             }
  76.         }
  77.         this.doProcess.add(chunks);
  78.     }
  79.  
  80.     private static abstract class AccumulativeRunnable<T extends Object> implements Runnable {
  81.  
  82.         private List<T> arguments = null;
  83.  
  84.         protected abstract void run(List<T> paramList);
  85.  
  86.         @Override
  87.         public final void run() {
  88.             this.run(this.flush());
  89.         }
  90.  
  91.         public final synchronized void add(T... toAdd) {
  92.             boolean mustSubmit = false;
  93.             if (this.arguments == null) {
  94.                 mustSubmit = true;
  95.                 this.arguments = new ArrayList<>();
  96.             }
  97.             addAll(this.arguments, toAdd);
  98.             if (mustSubmit) {
  99.                 this.submit();
  100.             }
  101.         }
  102.  
  103.         abstract protected void submit();
  104.  
  105.         private synchronized List<T> flush() {
  106.             List<T> localList = this.arguments;
  107.             this.arguments = null;
  108.             return localList;
  109.         }
  110.     }
  111.  
  112.     public interface Processor<T> {
  113.  
  114.         public void process(List<T> process);
  115.     }
  116.  
  117.     private class DoSubmitAccumulativeRunnable extends AccumulativeRunnable<Runnable> implements Runnable {
  118.  
  119.         /**
  120.          * Time in ticks between 2 invokings of the schedular
  121.          */
  122.         private final static int DELAY = 1;
  123.         /**
  124.          * The plugin, used to schedule tasks
  125.          */
  126.         private final Plugin plugin;
  127.  
  128.         public DoSubmitAccumulativeRunnable(Plugin plugin) {
  129.             this.plugin = plugin;
  130.         }
  131.  
  132.         @Override
  133.         protected void run(List<Runnable> args) {
  134.             for (Runnable runnable : args) {
  135.                 runnable.run();
  136.             }
  137.         }
  138.  
  139.         @Override
  140.         protected void submit() {
  141.             if (this.plugin.isEnabled()) {
  142.                 getScheduler().scheduleSyncDelayedTask(this.plugin, this, DELAY);
  143.             } else {
  144.                 // What do do, scheduling an task would throw an IllegalArgumentException, and enablking this plugin for a little time may cause bugs inside the plugin?
  145.                 // Mayby use reflection to access the enabled field of JavaPlugin, but this wont work whit plugins that dont exend that class
  146.                 throw new IllegalStateException("Plugin not enabled, unable to schadule task");
  147.             }
  148.         }
  149.     }
  150. }
Advertisement
Add Comment
Please, Sign In to add comment