All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bukkit.craftbukkit.scheduler.CraftAsyncTask Maven / Gradle / Ivy

package org.bukkit.craftbukkit.scheduler;

import org.apache.commons.lang.UnhandledException;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitWorker;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;


class CraftAsyncTask extends CraftTask {

  private final LinkedList workers = new LinkedList();
  private final Map runners;

  CraftAsyncTask(final Map runners, final Plugin plugin, final Runnable task, final int id, final long delay) {
    super(plugin, task, id, delay);
    this.runners = runners;
  }

  @Override
  public boolean isSync() {
    return false;
  }

  @Override
  public void run() {
    final Thread thread = Thread.currentThread();
    synchronized (workers) {
      if (getPeriod() == -2) {
        // Never continue running after cancelled.
        // Checking this with the lock is important!
        return;
      }
      workers.add(
        new BukkitWorker() {
          public Thread getThread() {
            return thread;
          }

          public int getTaskId() {
            return CraftAsyncTask.this.getTaskId();
          }

          public Plugin getOwner() {
            return CraftAsyncTask.this.getOwner();
          }
        });
    }
    Throwable thrown = null;
    try {
      super.run();
    } catch (final Throwable t) {
      thrown = t;
      throw new UnhandledException(
        String.format(
          "Plugin %s generated an exception while executing task %s",
          getOwner().getDescription().getFullName(),
          getTaskId()),
        thrown);
    } finally {
      // Cleanup is important for any async task, otherwise ghost tasks are everywhere
      synchronized (workers) {
        try {
          final Iterator workers = this.workers.iterator();
          boolean removed = false;
          while (workers.hasNext()) {
            if (workers.next().getThread() == thread) {
              workers.remove();
              removed = true; // Don't throw exception
              break;
            }
          }
          if (!removed) {
            throw new IllegalStateException(
              String.format(
                "Unable to remove worker %s on task %s for %s",
                thread.getName(),
                getTaskId(),
                getOwner().getDescription().getFullName()),
              thrown); // We don't want to lose the original exception, if any
          }
        } finally {
          if (getPeriod() < 0 && workers.isEmpty()) {
            // At this spot, we know we are the final async task being executed!
            // Because we have the lock, nothing else is running or will run because delay < 0
            runners.remove(getTaskId());
          }
        }
      }
    }
  }

  LinkedList getWorkers() {
    return workers;
  }

  boolean cancel0() {
    synchronized (workers) {
      // Synchronizing here prevents race condition for a completing task
      setPeriod(-2l);
      if (workers.isEmpty()) {
        runners.remove(getTaskId());
      }
    }
    return true;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy