javafx.concurrent.Task.java Source code

Java tutorial

Introduction

Here is the source code for javafx.concurrent.Task.java

Source

/*
 * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.concurrent;

import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.event.Event;
import javafx.event.EventDispatchChain;
import javafx.event.EventHandler;
import javafx.event.EventTarget;
import javafx.event.EventType;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicReference;
import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_CANCELLED;
import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_FAILED;
import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_RUNNING;
import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_SCHEDULED;
import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_SUCCEEDED;

/**
 * <p>
 *     A fully observable implementation of a {@link FutureTask}. {@code Task} exposes
 *     additional state and observable properties useful for programming asynchronous
 *     tasks in JavaFX, as defined in the {@link Worker} interface. An implementation
 *     of Task must override the {@link javafx.concurrent.Task#call()} method. This method
 *     is invoked on the background thread. Any state which is used in this method
 *     must be safe to read and write from a background thread. For example, manipulating
 *     a live scene graph from this method is unsafe and will result in runtime
 *     exceptions.
 * </p>
 * <p>
 *     Tasks are flexible and extremely useful for the encapsulation of "work". Because
 *     {@link Service} is designed to execute a Task, any Tasks defined by the application
 *     or library code can easily be used with a Service. Likewise, since Task extends
 *     from FutureTask, it is very easy and natural to use a Task with the java concurrency
 *     {@link java.util.concurrent.Executor} API. Since a Task is Runnable, you
 *     can also call it directly (by invoking the {@link javafx.concurrent.Task#run()} method)
 *     from another background thread. This allows for composition of work, or pass it to
 *     a new Thread constructed and executed manually. Finally, since you can
 *     manually create a new Thread, passing it a Runnable, it is possible to use
 *     the following idiom:
 * </p>
 *     <pre>{@code
 *         Thread th = new Thread(task);
 *         th.setDaemon(true);
 *         th.start();
 *     }</pre>
 * <p>
 *     Note that this code sets the daemon flag of the Thread to true. If you
 *     want a background thread to prevent the VM from exiting after the last
 *     stage is closed, then you would want daemon to be false. However, if
 *     you want the background threads to simply terminate after all the
 *     stages are closed, then you must set daemon to true.
 * </p>
 * <p>
 *     Although {@link java.util.concurrent.ExecutorService} defines several methods which
 *     take a Runnable, you should generally limit yourself to using the <code>execute</code>
 *     method inherited from {@link java.util.concurrent.Executor}.
 * </p>
 * <p>
 *     As with FutureTask, a Task is a one-shot class and cannot be reused. See {@link Service}
 *     for a reusable {@link Worker}.
 * </p>
 * <p>
 *     Because the Task is designed for use with JavaFX GUI applications, it ensures
 *     that every change to its public properties, as well as change notifications
 *     for state, errors, and for event handlers, all occur on the main JavaFX application
 *     thread. Accessing these properties from a background thread (including the
 *     {@link #call()} method) will result in runtime exceptions being raised. The only exception
 *     to this, is when initially configuring a Task, which may safely be done
 *     from any thread. However, once the Task has been initialized and
 *     started, it may only thereafter be used from the FX thread (except for those methods clearly
 *     marked as being appropriate for the subclass to invoke from the background thread).
 * </p>
 * <p>
 *     It is <strong>strongly encouraged</strong> that all Tasks be initialized with
 *     immutable state upon which the Task will operate. This should be done by providing
 *     a Task constructor which takes the parameters necessary for execution of the Task.
 *     Immutable state makes it easy and safe to use from any thread and ensures
 *     correctness in the presence of multiple threads.
 * </p>
 * <p>
 *     In Java there is no reliable way to "kill" a thread in process. However,
 *     when <code>cancel</code> is called on a Task, it is important that
 *     the Task stop processing. A "run-away" Task might continue processing
 *     and updating the message, text, and progress properties even after the
 *     Task has been cancelled! In Java, cancelling a Task is a cooperative
 *     endeavor. The user of the Task will request that it be cancelled, and
 *     the author of the Task must check whether is has been cancelled within
 *     the body of the <code>call</code> method. There are two ways this can
 *     be done. First, the Task author may check the isCancelled method,
 *     inherited from <code>FutureTask</code>, to see whether the Task has
 *     been cancelled. Second, if the Task implementation makes use of any
 *     blocking calls (such as NIO InterruptibleChannels or Thread.sleep) and
 *     the task is cancelled while in such a blocking call, an
 *     InterruptedException is thrown. Task implementations which have blocking
 *     calls should recognize that an interrupted thread may be the signal for
 *     a cancelled task and should double check the isCancelled method to ensure
 *     that the InterruptedException was thrown due to the cancellation of the
 *     Task.
 * </p>
 * <h2>Examples</h2>
 * <p>
 *     The following set of examples demonstrate some of the most common uses of
 *     Tasks.
 * </p>
 *
 * <h3>A Simple Loop</h3>
 *
 * <p>
 *     The first example is a simple loop that does nothing particularly useful,
 *     but demonstrates the fundamental aspects of writing a Task correctly. This
 *     example will simply loop and print to standard out on each loop iteration.
 *     When it completes, it returns the number of times it iterated.
 * </p>
 *
 * <pre><code>
 *     {@literal Task<Integer> task = new Task<Integer>()} {
 *         {@literal @Override} protected Integer call() throws Exception {
 *             int iterations;
 *             {@literal for (iterations = 0; iterations < 100000; iterations++)} {
 *                 if (isCancelled()) {
 *                     break;
 *                 }
 *                 System.out.println("Iteration " + iterations);
 *             }
 *             return iterations;
 *         }
 *     };
 * </code></pre>
 *
 * <p>
 *     First, we define what type of value is returned from this Task. In this
 *     case, we want to return the number of times we iterated, so we will
 *     specify the Task to be of type Integer by using generics. Then, within
 *     the implementation of the <code>call</code> method, we iterate from
 *     0 to 100000. On each iteration, we check to see whether this Task has
 *     been cancelled. If it has been, then we break out of the loop and return
 *     the number of times we iterated. Otherwise a message is printed to
 *     the console and the iteration count increased and we continue looping.
 * </p>
 *
 * <p>
 *     Checking for isCancelled() in the loop body is critical, otherwise the
 *     developer may cancel the task, but the task will continue running
 *     and updating both the progress and returning the incorrect result
 *     from the end of the <code>call</code> method. A correct implementation
 *     of a Task will always check for cancellation.
 * </p>
 *
 * <h3>A Simple Loop With Progress Notification</h3>
 *
 * <p>
 *     Similar to the previous example, except this time we will modify the
 *     progress of the Task in each iteration. Note that we have a choice
 *     to make in the case of cancellation. Do we want to set the progress back
 *     to -1 (indeterminate) when the Task is cancelled, or do we want to leave
 *     the progress where it was at? In this case, let's leave the progress alone
 *     and only update the message on cancellation, though updating the
 *     progress after cancellation is a perfectly valid choice.
 * </p>
 *
 * <pre><code>
 *     {@literal Task<Integer> task = new Task<Integer>()} {
 *         {@literal @Override} protected Integer call() throws Exception {
 *             int iterations;
 *             {@literal for (iterations = 0; iterations < 10000000; iterations++)} {
 *                 if (isCancelled()) {
 *                     updateMessage("Cancelled");
 *                     break;
 *                 }
 *                 updateMessage("Iteration " + iterations);
 *                 updateProgress(iterations, 10000000);
 *             }
 *             return iterations;
 *         }
 *     };
 * </code></pre>
 *
 * <p>
 *     As before, within the for loop we check whether the Task has been
 *     cancelled. If it has been cancelled, we will update the Task's
 *     message to indicate that it has been cancelled, and then break as
 *     before. If the Task has not been cancelled, then we will update its
 *     message to indicate the current iteration and then update the
 *     progress to indicate the current progress.
 * </p>
 *
 * <h3>A Simple Loop With Progress Notification And Blocking Calls</h3>
 *
 * <p>
 *     This example adds to the previous examples a blocking call. Because a
 *     blocking call may thrown an InterruptedException, and because an
 *     InterruptedException may occur as a result of the Task being cancelled,
 *     we need to be sure to handle the InterruptedException and check on the
 *     cancel state.
 * </p>
 *
 * <pre><code>
 *     {@literal Task<Integer> task = new Task<Integer>()} {
 *         {@literal @Override} protected Integer call() throws Exception {
 *             int iterations;
 *             {@literal for (iterations = 0; iterations < 1000; iterations++)} {
 *                 if (isCancelled()) {
 *                     updateMessage("Cancelled");
 *                     break;
 *                 }
 *                 updateMessage("Iteration " + iterations);
 *                 updateProgress(iterations, 1000);
 *
 *                 // Now block the thread for a short time, but be sure
 *                 // to check the interrupted exception for cancellation!
 *                 try {
 *                     Thread.sleep(100);
 *                 } catch (InterruptedException interrupted) {
 *                     if (isCancelled()) {
 *                         updateMessage("Cancelled");
 *                         break;
 *                     }
 *                 }
 *             }
 *             return iterations;
 *         }
 *     };
 * </code></pre>
 *
 * <p>
 *     Here we have added to the body of the loop a <code>Thread.sleep</code>
 *     call. Since this is a blocking call, I have to handle the potential
 *     InterruptedException. Within the catch block, I will check whether
 *     the Task has been cancelled, and if so, update the message accordingly
 *     and break out of the loop.
 * </p>
 *
 * <h3>A Task Which Takes Parameters</h3>
 *
 * <p>
 *     Most Tasks require some parameters in order to do useful work. For
 *     example, a DeleteRecordTask needs the object or primary key to delete
 *     from the database. A ReadFileTask needs the URI of the file to be read.
 *     Because Tasks operate on a background thread, care must be taken to
 *     make sure the body of the <code>call</code> method does not read or
 *     modify any shared state. There are two techniques most useful for
 *     doing this: using final variables, and passing variables to a Task
 *     during construction.
 * </p>
 *
 * <p>
 *     When using a Task as an anonymous class, the most natural way to pass
 *     parameters to the Task is by using final variables. In this example,
 *     we pass to the Task the total number of times the Task should iterate.
 * </p>
 *
 * <pre><code>
 *     final int totalIterations = 9000000;
 *     {@literal Task<Integer> task = new Task<Integer>()} {
 *         {@literal @Override} protected Integer call() throws Exception {
 *             int iterations;
 *             {@literal for (iterations = 0; iterations < totalIterations; iterations++)} {
 *                 if (isCancelled()) {
 *                     updateMessage("Cancelled");
 *                     break;
 *                 }
 *                 updateMessage("Iteration " + iterations);
 *                 updateProgress(iterations, totalIterations);
 *             }
 *             return iterations;
 *         }
 *     };
 * </code></pre>
 *
 * <p>
 *     Since <code>totalIterations</code> is final, the <code>call</code>
 *     method can safely read it and refer to it from a background thread.
 * </p>
 *
 * <p>
 *     When writing Task libraries (as opposed to specific-use implementations),
 *     we need to use a different technique. In this case, I will create an
 *     IteratingTask which performs the same work as above. This time, since
 *     the IteratingTask is defined in its own file, it will need to have
 *     parameters passed to it in its constructor. These parameters are
 *     assigned to final variables.
 * </p>
 *
 * <pre><code>
 *     {@literal public class IteratingTask extends Task<Integer>} {
 *         private final int totalIterations;
 *
 *         public IteratingTask(int totalIterations) {
 *             this.totalIterations = totalIterations;
 *         }
 *
 *         {@literal @Override} protected Integer call() throws Exception {
 *             int iterations = 0;
 *             {@literal for (iterations = 0; iterations < totalIterations; iterations++)} {
 *                 if (isCancelled()) {
 *                     updateMessage("Cancelled");
 *                     break;
 *                 }
 *                 updateMessage("Iteration " + iterations);
 *                 updateProgress(iterations, totalIterations);
 *             }
 *             return iterations;
 *         }
 *     }
 * </code></pre>
 *
 * <p>And then when used:</p>
 *
 * <pre>{@code
 *     IteratingTask task = new IteratingTask(8000000);
 * }</pre>
 *
 * <p>In this way, parameters are passed to the IteratingTask in a safe
 * manner, and again, are final. Thus, the <code>call</code> method can
 * safely read this state from a background thread.</p>
 *
 * <p>WARNING: Do not pass mutable state to a Task and then operate on it
 * from a background thread. Doing so may introduce race conditions. In
 * particular, suppose you had a SaveCustomerTask which took a Customer
 * in its constructor. Although the SaveCustomerTask may have a final
 * reference to the Customer, if the Customer object is mutable, then it
 * is possible that both the SaveCustomerTask and some other application code
 * will be reading or modifying the state of the Customer from different
 * threads. Be very careful in such cases, that while a mutable object such
 * as this Customer is being used from a background thread, that it is
 * not being used also from another thread. In particular, if the background
 * thread is reading data from the database and updating the Customer object,
 * and the Customer object is bound to scene graph nodes (such as UI
 * controls), then there could be a violation of threading rules! For such
 * cases, modify the Customer object from the FX Application Thread rather
 * than from the background thread.</p>
 *
 * <pre><code>
 *     {@literal public class UpdateCustomerTask extends Task<Customer>} {
 *         private final Customer customer;
 *
 *         public UpdateCustomerTask(Customer customer) {
 *             this.customer = customer;
 *         }
 *
 *         {@literal @Override} protected Customer call() throws Exception {
 *             // pseudo-code:
 *             //   query the database
 *             //   read the values
 *
 *             // Now update the customer
 *             Platform.runLater(new Runnable() {
 *                 {@literal @Override} public void run() {
 *                     customer.setFirstName(rs.getString("FirstName"));
 *                     // etc
 *                 }
 *             });
 *
 *             return customer;
 *         }
 *     }
 * </code></pre>
 *
 * <h3>A Task Which Returns No Value</h3>
 *
 * <p>
 *     Many, if not most, Tasks should return a value upon completion. For
 *     CRUD Tasks, one would expect that a "Create" Task would return the newly
 *     created object or primary key, a "Read" Task would return the read
 *     object, an "Update" task would return the number of records updated,
 *     and a "Delete" task would return the number of records deleted.
 * </p>
 *
 * <p>
 *     However sometimes there just isn't anything truly useful to return.
 *     For example, I might have a Task which writes to a file. Task has built
 *     into it a mechanism for indicating whether it has succeeded or failed
 *     along with the number of bytes written (the progress), and thus there is
 *     nothing really for me to return. In such a case, you can use the Void
 *     type. This is a special type in the Java language which can only be
 *     assigned the value of <code>null</code>. You would use it as follows:
 * </p>
 *
 * <pre><code>
 *     final String filePath = "/foo.txt";
 *     final String contents = "Some contents";
 *     {@literal Task<Void> task = new Task<Void>()} {
 *         {@literal @Override} protected Void call() throws Exception {
 *             File file = new File(filePath);
 *             FileOutputStream out = new FileOutputStream(file);
 *             // ... and other code to write the contents ...
 *
 *             // Return null at the end of a Task of type Void
 *             return null;
 *         }
 *     };
 * </code></pre>
 *
 * <h3>A Task Which Returns An ObservableList</h3>
 *
 * <p>Because the ListView, TableView, and other UI controls and scene graph
 * nodes make use of ObservableList, it is common to want to create and return
 * an ObservableList from a Task. When you do not care to display intermediate
 * values, the easiest way to correctly write such a Task is simply to
 * construct an ObservableList within the <code>call</code> method, and then
 * return it at the conclusion of the Task.</p>
 *
 * <pre><code>
 *     {@literal Task<ObservableList<Rectangle>> task = new Task<ObservableList<Rectangle>>}() {
 *         {@literal @Override protected ObservableList<Rectangle> call() throws Exception} {
 *             updateMessage("Creating Rectangles");
 *             {@literal ObservableList<Rectangle> results = FXCollections.observableArrayList();}
 *             {@literal for (int i=0; i<100; i++)} {
 *                 if (isCancelled()) break;
 *                 Rectangle r = new Rectangle(10, 10);
 *                 r.setX(10 * i);
 *                 results.add(r);
 *                 updateProgress(i, 100);
 *             }
 *             return results;
 *         }
 *     };
 * </code></pre>
 *
 * <p>In the above example, we are going to create 100 rectangles and return
 * them from this task. An ObservableList is created within the
 * <code>call</code> method, populated, and then returned.</p>
 *
 * <h3>A Task Which Returns Partial Results</h3>
 *
 * <p>Sometimes you want to create a Task which will return partial results.
 * Perhaps you are building a complex scene graph and want to show the
 * scene graph as it is being constructed. Or perhaps you are reading a large
 * amount of data over the network and want to display the entries in a
 * TableView as the data is arriving. In such cases, there is some shared state
 * available both to the FX Application Thread and the background thread.
 * Great care must be taken to <strong>never update shared state from any
 * thread other than the FX Application Thread</strong>.</p>
 *
 * <p>The easiest way to do this is to take advantage of the {@link #updateValue(Object)} method.
 * This method may be called repeatedly from the background thread. Updates are coalesced to
 * prevent saturation of the FX event queue. This means you can call it as frequently as
 * you like from the background thread but only the most recent set is ultimately set.</p>
 *
 * <pre><code>
 *     {@literal Task<Long> task = new Task<Long>()} {
 *         {@literal @Override} protected Long call() throws Exception {
 *             long a = 0;
 *             long b = 1;
 *             {@literal for (long i = 0; i < Long.MAX_VALUE; i++)} {
 *                 updateValue(a);
 *                 a += b;
 *                 b = a - b;
 *             }
 *             return a;
 *         }
 *     };
 * </code></pre>
 *
 * <p>Another way to do this is to expose a new property on the Task
 * which will represent the partial result. Then make sure to use
 * <code>Platform.runLater</code> when updating the partial result.</p>
 *
 * <pre><code>
 *     {@literal Task<Long> task = new Task<Long>()} {
 *         {@literal @Override} protected Long call() throws Exception {
 *             long a = 0;
 *             long b = 1;
 *             {@literal for (long i = 0; i < Long.MAX_VALUE; i++)} {
 *                 final long v = a;
 *                 Platform.runLater(new Runnable() {
 *                     {@literal @Override} public void run() {
 *                         updateValue(v);
 *                     }
 *                 }
 *                 a += b;
 *                 b = a - b;
 *             }
 *             return a;
 *         }
 *     };
 * </code></pre>
 *
 * <p>Suppose instead of updating a single value, you want to populate an ObservableList
 * with results as they are obtained. One approach is to expose a new property on the Task
 * which will represent the partial result. Then make sure to use
 * <code>Platform.runLater</code> when adding new items to the partial
 * result.</p>
 *
 * <pre><code>
 *     {@literal public class PartialResultsTask extends Task<ObservableList<Rectangle>>} {
 *         // Uses Java 7 diamond operator
 *         {@literal private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults =}
 *                 {@literal new ReadOnlyObjectWrapper<>(this, "partialResults",
 *                         FXCollections.observableArrayList(new ArrayList<Rectangle>()));}
 *
 *         {@literal public final ObservableList<Rectangle> getPartialResults()} { return partialResults.get(); }
 *         {@literal public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty()} {
 *             return partialResults.getReadOnlyProperty();
 *         }
 *
 *         {@literal @Override protected ObservableList<Rectangle> call() throws Exception} {
 *             updateMessage("Creating Rectangles...");
 *             {@literal for (int i=0; i<100; i++)} {
 *                 if (isCancelled()) break;
 *                 final Rectangle r = new Rectangle(10, 10);
 *                 r.setX(10 * i);
 *                 Platform.runLater(new Runnable() {
 *                     {@literal @Override} public void run() {
 *                         partialResults.get().add(r);
 *                     }
 *                 });
 *                 updateProgress(i, 100);
 *             }
 *             return partialResults.get();
 *         }
 *     }
 * </code></pre>
 *
 * <h3>A Task Which Modifies The Scene Graph</h3>
 *
 * <p>Generally, Tasks should not interact directly with the UI. Doing so
 * creates a tight coupling between a specific Task implementation and a
 * specific part of your UI. However, when you do want to create such a
 * coupling, you must ensure that you use <code>Platform.runLater</code>
 * so that any modifications of the scene graph occur on the
 * FX Application Thread.</p>
 *
 * <pre><code>
 *     final Group group = new Group();
 *     {@literal Task<Void> task = new Task<Void>()} {
 *         {@literal @Override} protected Void call() throws Exception {
 *             {@literal for (int i=0; i<100; i++)} {
 *                 if (isCancelled()) break;
 *                 final Rectangle r = new Rectangle(10, 10);
 *                 r.setX(10 * i);
 *                 Platform.runLater(new Runnable() {
 *                     {@literal @Override} public void run() {
 *                         group.getChildren().add(r);
 *                     }
 *                 });
 *             }
 *             return null;
 *         }
 *     };
 * </code></pre>
 *
 * <h3>Reacting To State Changes Generically</h3>
 *
 * <p>Sometimes you may want to write a Task which updates its progress,
 * message, text, or in some other way reacts whenever a state change
 * happens on the Task. For example, you may want to change the status
 * message on the Task on Failure, Success, Running, or Cancelled state changes.
 * </p>
 * <pre><code>
 *     {@literal Task<Integer> task = new Task<Integer>()} {
 *         {@literal @Override} protected Integer call() throws Exception {
 *             int iterations = 0;
 *             {@literal for (iterations = 0; iterations < 100000; iterations++)} {
 *                 if (isCancelled()) {
 *                     break;
 *                 }
 *                 System.out.println("Iteration " + iterations);
 *             }
 *             return iterations;
 *         }
 *
 *         {@literal @Override} protected void succeeded() {
 *             super.succeeded();
 *             updateMessage("Done!");
 *         }
 *
 *         {@literal @Override} protected void cancelled() {
 *             super.cancelled();
 *             updateMessage("Cancelled!");
 *         }
 *
 *         {@literal @Override} protected void failed() {
 *             super.failed();
 *             updateMessage("Failed!");
 *         }
 *     };
 * </code></pre>
 * @since JavaFX 2.0
 */
public abstract class Task<V> extends FutureTask<V> implements Worker<V>, EventTarget {
    /**
     * Used to send workDone updates in a thread-safe manner from the subclass
     * to the FX application thread and workDone related properties. AtomicReference
     * is used so as to coalesce updates such that we don't flood the event queue.
     */
    private AtomicReference<ProgressUpdate> progressUpdate = new AtomicReference<>();

    /**
     * Used to send message updates in a thread-safe manner from the subclass
     * to the FX application thread. AtomicReference is used so as to coalesce
     * updates such that we don't flood the event queue.
     */
    private AtomicReference<String> messageUpdate = new AtomicReference<>();

    /**
     * Used to send title updates in a thread-safe manner from the subclass
     * to the FX application thread. AtomicReference is used so as to coalesce
     * updates such that we don't flood the event queue.
     */
    private AtomicReference<String> titleUpdate = new AtomicReference<>();

    /**
     * Used to send value updates in a thread-safe manner from the subclass
     * to the FX application thread. AtomicReference is used so as to coalesce
     * updates such that we don't flood the event queue.
     */
    private AtomicReference<V> valueUpdate = new AtomicReference<>();

    /**
     * This is used so we have a thread-safe way to ask whether the task was
     * started in the checkThread() method.
     */
    private volatile boolean started = false;

    /**
     * Creates a new Task.
     */
    public Task() {
        this(new TaskCallable<V>());
    }

    /**
     * This bit of construction trickery is necessary because otherwise there is
     * no way for the main constructor to both create the callable and maintain
     * a reference to it, which is necessary because an anonymous callable construction
     * cannot reference the implicit "this". We leverage an internal Callable
     * so that all the pre-built semantics around cancel and so forth are
     * handled correctly.
     *
     * @param callableAdapter non-null implementation of the
     *                        TaskCallable adapter
     */
    private Task(final TaskCallable<V> callableAdapter) {
        super(callableAdapter);
        callableAdapter.task = this;
    }

    /**
     * Invoked when the Task is executed, the call method must be overridden and
     * implemented by subclasses. The call method actually performs the
     * background thread logic. Only the updateProgress, updateMessage, updateValue and
     * updateTitle methods of Task may be called from code within this method.
     * Any other interaction with the Task from the background thread will result
     * in runtime exceptions.
     *
     * @return The result of the background work, if any.
     * @throws Exception an unhandled exception which occurred during the
     *         background operation
     */
    protected abstract V call() throws Exception;

    private ObjectProperty<State> state = new SimpleObjectProperty<>(this, "state", State.READY);

    final void setState(State value) { // package access for the Service
        checkThread();
        final State s = getState();
        if (s != State.CANCELLED) {
            this.state.set(value);
            // Make sure the running flag is set
            setRunning(value == State.SCHEDULED || value == State.RUNNING);

            // Invoke the event handlers, and then call the protected methods.
            switch (state.get()) {
            case CANCELLED:
                fireEvent(new WorkerStateEvent(this, WORKER_STATE_CANCELLED));
                cancelled();
                break;
            case FAILED:
                fireEvent(new WorkerStateEvent(this, WORKER_STATE_FAILED));
                failed();
                break;
            case READY:
                // This even can never meaningfully occur, because the
                // Task begins life as ready and can never go back to it!
                break;
            case RUNNING:
                fireEvent(new WorkerStateEvent(this, WORKER_STATE_RUNNING));
                running();
                break;
            case SCHEDULED:
                fireEvent(new WorkerStateEvent(this, WORKER_STATE_SCHEDULED));
                scheduled();
                break;
            case SUCCEEDED:
                fireEvent(new WorkerStateEvent(this, WORKER_STATE_SUCCEEDED));
                succeeded();
                break;
            default:
                throw new AssertionError("Should be unreachable");
            }
        }
    }

    @Override
    public final State getState() {
        checkThread();
        return state.get();
    }

    @Override
    public final ReadOnlyObjectProperty<State> stateProperty() {
        checkThread();
        return state;
    }

    /**
     * The onSchedule event handler is called whenever the Task state
     * transitions to the SCHEDULED state.
     *
     * @return the onScheduled event handler property
     * @since JavaFX 2.1
     */
    public final ObjectProperty<EventHandler<WorkerStateEvent>> onScheduledProperty() {
        checkThread();
        return getEventHelper().onScheduledProperty();
    }

    /**
     * The onSchedule event handler is called whenever the Task state
     * transitions to the SCHEDULED state.
     *
     * @return the onScheduled event handler, if any
     * @since JavaFX 2.1
     */
    public final EventHandler<WorkerStateEvent> getOnScheduled() {
        checkThread();
        return eventHelper == null ? null : eventHelper.getOnScheduled();
    }

    /**
     * The onSchedule event handler is called whenever the Task state
     * transitions to the SCHEDULED state.
     *
     * @param value the event handler, can be null to clear it
     * @since JavaFX 2.1
     */
    public final void setOnScheduled(EventHandler<WorkerStateEvent> value) {
        checkThread();
        getEventHelper().setOnScheduled(value);
    }

    /**
     * A protected convenience method for subclasses, called whenever the
     * state of the Task has transitioned to the SCHEDULED state.
     * This method is invoked on the FX Application Thread after the Task has been fully transitioned to
     * the new state.
     * @since JavaFX 2.1
     */
    protected void scheduled() {
    }

    /**
     * The onRunning event handler is called whenever the Task state
     * transitions to the RUNNING state.
     *
     * @return the onRunning event handler property
     * @since JavaFX 2.1
     */
    public final ObjectProperty<EventHandler<WorkerStateEvent>> onRunningProperty() {
        checkThread();
        return getEventHelper().onRunningProperty();
    }

    /**
     * The onRunning event handler is called whenever the Task state
     * transitions to the RUNNING state.
     *
     * @return the onRunning event handler, if any
     * @since JavaFX 2.1
     */
    public final EventHandler<WorkerStateEvent> getOnRunning() {
        checkThread();
        return eventHelper == null ? null : eventHelper.getOnRunning();
    }

    /**
     * The onRunning event handler is called whenever the Task state
     * transitions to the RUNNING state.
     *
     * @param value the event handler, can be null to clear it
     * @since JavaFX 2.1
     */
    public final void setOnRunning(EventHandler<WorkerStateEvent> value) {
        checkThread();
        getEventHelper().setOnRunning(value);
    }

    /**
     * A protected convenience method for subclasses, called whenever the
     * state of the Task has transitioned to the RUNNING state.
     * This method is invoked on the FX Application Thread after the Task has been fully transitioned to
     * the new state.
     * @since JavaFX 2.1
     */
    protected void running() {
    }

    /**
     * The onSucceeded event handler is called whenever the Task state
     * transitions to the SUCCEEDED state.
     *
     * @return the onSucceeded event handler property
     * @since JavaFX 2.1
     */
    public final ObjectProperty<EventHandler<WorkerStateEvent>> onSucceededProperty() {
        checkThread();
        return getEventHelper().onSucceededProperty();
    }

    /**
     * The onSucceeded event handler is called whenever the Task state
     * transitions to the SUCCEEDED state.
     *
     * @return the onSucceeded event handler, if any
     * @since JavaFX 2.1
     */
    public final EventHandler<WorkerStateEvent> getOnSucceeded() {
        checkThread();
        return eventHelper == null ? null : eventHelper.getOnSucceeded();
    }

    /**
     * The onSucceeded event handler is called whenever the Task state
     * transitions to the SUCCEEDED state.
     *
     * @param value the event handler, can be null to clear it
     * @since JavaFX 2.1
     */
    public final void setOnSucceeded(EventHandler<WorkerStateEvent> value) {
        checkThread();
        getEventHelper().setOnSucceeded(value);
    }

    /**
     * A protected convenience method for subclasses, called whenever the
     * state of the Task has transitioned to the SUCCEEDED state.
     * This method is invoked on the FX Application Thread after the Task has been fully transitioned to
     * the new state.
     * @since JavaFX 2.1
     */
    protected void succeeded() {
    }

    /**
     * The onCancelled event handler is called whenever the Task state
     * transitions to the CANCELLED state.
     *
     * @return the onCancelled event handler property
     * @since JavaFX 2.1
     */
    public final ObjectProperty<EventHandler<WorkerStateEvent>> onCancelledProperty() {
        checkThread();
        return getEventHelper().onCancelledProperty();
    }

    /**
     * The onCancelled event handler is called whenever the Task state
     * transitions to the CANCELLED state.
     *
     * @return the onCancelled event handler, if any
     * @since JavaFX 2.1
     */
    public final EventHandler<WorkerStateEvent> getOnCancelled() {
        checkThread();
        return eventHelper == null ? null : eventHelper.getOnCancelled();
    }

    /**
     * The onCancelled event handler is called whenever the Task state
     * transitions to the CANCELLED state.
     *
     * @param value the event handler, can be null to clear it
     * @since JavaFX 2.1
     */
    public final void setOnCancelled(EventHandler<WorkerStateEvent> value) {
        checkThread();
        getEventHelper().setOnCancelled(value);
    }

    /**
     * A protected convenience method for subclasses, called whenever the
     * state of the Task has transitioned to the CANCELLED state.
     * This method is invoked on the FX Application Thread after the Task has been fully transitioned to
     * the new state.
     * @since JavaFX 2.1
     */
    protected void cancelled() {
    }

    /**
     * The onFailed event handler is called whenever the Task state
     * transitions to the FAILED state.
     *
     * @return the onFailed event handler property
     * @since JavaFX 2.1
     */
    public final ObjectProperty<EventHandler<WorkerStateEvent>> onFailedProperty() {
        checkThread();
        return getEventHelper().onFailedProperty();
    }

    /**
     * The onFailed event handler is called whenever the Task state
     * transitions to the FAILED state.
     *
     * @return the onFailed event handler, if any
     * @since JavaFX 2.1
     */
    public final EventHandler<WorkerStateEvent> getOnFailed() {
        checkThread();
        return eventHelper == null ? null : eventHelper.getOnFailed();
    }

    /**
     * The onFailed event handler is called whenever the Task state
     * transitions to the FAILED state.
     *
     * @param value the event handler, can be null to clear it
     * @since JavaFX 2.1
     */
    public final void setOnFailed(EventHandler<WorkerStateEvent> value) {
        checkThread();
        getEventHelper().setOnFailed(value);
    }

    /**
     * A protected convenience method for subclasses, called whenever the
     * state of the Task has transitioned to the FAILED state.
     * This method is invoked on the FX Application Thread after the Task has been fully transitioned to
     * the new state.
     * @since JavaFX 2.1
     */
    protected void failed() {
    }

    private final ObjectProperty<V> value = new SimpleObjectProperty<>(this, "value");

    private void setValue(V v) {
        checkThread();
        value.set(v);
    }

    @Override
    public final V getValue() {
        checkThread();
        return value.get();
    }

    @Override
    public final ReadOnlyObjectProperty<V> valueProperty() {
        checkThread();
        return value;
    }

    private final ObjectProperty<Throwable> exception = new SimpleObjectProperty<>(this, "exception");

    private void _setException(Throwable value) {
        checkThread();
        exception.set(value);
    }

    @Override
    public final Throwable getException() {
        checkThread();
        return exception.get();
    }

    @Override
    public final ReadOnlyObjectProperty<Throwable> exceptionProperty() {
        checkThread();
        return exception;
    }

    private final DoubleProperty workDone = new SimpleDoubleProperty(this, "workDone", -1);

    private void setWorkDone(double value) {
        checkThread();
        workDone.set(value);
    }

    @Override
    public final double getWorkDone() {
        checkThread();
        return workDone.get();
    }

    @Override
    public final ReadOnlyDoubleProperty workDoneProperty() {
        checkThread();
        return workDone;
    }

    private final DoubleProperty totalWork = new SimpleDoubleProperty(this, "totalWork", -1);

    private void setTotalWork(double value) {
        checkThread();
        totalWork.set(value);
    }

    @Override
    public final double getTotalWork() {
        checkThread();
        return totalWork.get();
    }

    @Override
    public final ReadOnlyDoubleProperty totalWorkProperty() {
        checkThread();
        return totalWork;
    }

    private final DoubleProperty progress = new SimpleDoubleProperty(this, "progress", -1);

    private void setProgress(double value) {
        checkThread();
        progress.set(value);
    }

    @Override
    public final double getProgress() {
        checkThread();
        return progress.get();
    }

    @Override
    public final ReadOnlyDoubleProperty progressProperty() {
        checkThread();
        return progress;
    }

    private final BooleanProperty running = new SimpleBooleanProperty(this, "running", false);

    private void setRunning(boolean value) {
        checkThread();
        running.set(value);
    }

    @Override
    public final boolean isRunning() {
        checkThread();
        return running.get();
    }

    @Override
    public final ReadOnlyBooleanProperty runningProperty() {
        checkThread();
        return running;
    }

    private final StringProperty message = new SimpleStringProperty(this, "message", "");

    @Override
    public final String getMessage() {
        checkThread();
        return message.get();
    }

    @Override
    public final ReadOnlyStringProperty messageProperty() {
        checkThread();
        return message;
    }

    private final StringProperty title = new SimpleStringProperty(this, "title", "");

    @Override
    public final String getTitle() {
        checkThread();
        return title.get();
    }

    @Override
    public final ReadOnlyStringProperty titleProperty() {
        checkThread();
        return title;
    }

    @Override
    public final boolean cancel() {
        return cancel(true);
    }

    // Need to assert the modifyThread permission so an app can cancel
    // a task that it created (the default executor for the service runs in
    // its own thread group)
    // Note that this is needed when running with a security manager.
    private static final Permission modifyThreadPerm = new RuntimePermission("modifyThread");

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        // Delegate to the super implementation to actually attempt to cancel this thing
        // Assert the modifyThread permission
        boolean flag = AccessController.doPrivileged(
                (PrivilegedAction<Boolean>) () -> super.cancel(mayInterruptIfRunning), null, modifyThreadPerm);

        // If cancel succeeded (according to the semantics of the Future cancel method),
        // then we need to make sure the State flag is set appropriately
        if (flag) {
            // If this method was called on the FX application thread, then we can
            // just update the state directly and this will make sure that after
            // the cancel method was called, the state will be set correctly
            // (otherwise it would be indeterminate). However if the cancel method was
            // called off the FX app thread, then we must use runLater, and the
            // state flag will not be readable immediately after this call. However,
            // that would be the case anyway since these properties are not thread-safe.
            if (isFxApplicationThread()) {
                setState(State.CANCELLED);
            } else {
                runLater(() -> setState(State.CANCELLED));
            }
        }
        // return the flag
        return flag;
    }

    /**
     * Updates the <code>workDone</code>, <code>totalWork</code>,
     * and <code>progress</code> properties. Calls to updateProgress
     * are coalesced and run later on the FX application thread, and calls
     * to updateProgress, even from the FX Application thread, may not
     * necessarily result in immediate updates to these properties, and
     * intermediate workDone values may be coalesced to save on event
     * notifications. <code>max</code> becomes the new value for
     * <code>totalWork</code>.
     * <p>
     *     <em>This method is safe to be called from any thread.</em>
     * </p>
     *
     * @param workDone A value from Long.MIN_VALUE up to max. If the value is greater
     *                 than max, then it will be clamped at max.
     *                 If the value passed is negative then the resulting percent
     *                 done will be -1 (thus, indeterminate).
     * @param max A value from Long.MIN_VALUE to Long.MAX_VALUE.
     * @see #updateProgress(double, double)
     */
    protected void updateProgress(long workDone, long max) {
        updateProgress((double) workDone, (double) max);
    }

    /**
     * Updates the <code>workDone</code>, <code>totalWork</code>,
     * and <code>progress</code> properties. Calls to updateProgress
     * are coalesced and run later on the FX application thread, and calls
     * to updateProgress, even from the FX Application thread, may not
     * necessarily result in immediate updates to these properties, and
     * intermediate workDone values may be coalesced to save on event
     * notifications. <code>max</code> becomes the new value for
     * <code>totalWork</code>.
     * <p>
     *     <em>This method is safe to be called from any thread.</em>
     * </p>
     *
     * @param workDone A value from Double.MIN_VALUE up to max. If the value is greater
     *                 than max, then it will be clamped at max.
     *                 If the value passed is negative, or Infinity, or NaN,
     *                 then the resulting percentDone will be -1 (thus, indeterminate).
     * @param max A value from Double.MIN_VALUE to Double.MAX_VALUE. Infinity and NaN are treated as -1.
     * @since JavaFX 2.2
     */
    protected void updateProgress(double workDone, double max) {
        // Adjust Infinity / NaN to be -1 for both workDone and max.
        if (Double.isInfinite(workDone) || Double.isNaN(workDone)) {
            workDone = -1;
        }

        if (Double.isInfinite(max) || Double.isNaN(max)) {
            max = -1;
        }

        if (workDone < 0) {
            workDone = -1;
        }

        if (max < 0) {
            max = -1;
        }

        // Clamp the workDone if necessary so as not to exceed max
        if (workDone > max) {
            workDone = max;
        }

        if (isFxApplicationThread()) {
            _updateProgress(workDone, max);
        } else if (progressUpdate.getAndSet(new ProgressUpdate(workDone, max)) == null) {
            runLater(() -> {
                final ProgressUpdate update = progressUpdate.getAndSet(null);
                _updateProgress(update.workDone, update.totalWork);
            });
        }
    }

    private void _updateProgress(double workDone, double max) {
        setTotalWork(max);
        setWorkDone(workDone);
        if (workDone == -1) {
            setProgress(-1);
        } else {
            setProgress(workDone / max);
        }
    }

    /**
     * Updates the <code>message</code> property. Calls to updateMessage
     * are coalesced and run later on the FX application thread, so calls
     * to updateMessage, even from the FX Application thread, may not
     * necessarily result in immediate updates to this property, and
     * intermediate message values may be coalesced to save on event
     * notifications.
     * <p>
     *     <em>This method is safe to be called from any thread.</em>
     * </p>
     *
     * @param message the new message
     */
    protected void updateMessage(String message) {
        if (isFxApplicationThread()) {
            this.message.set(message);
        } else {
            // As with the workDone, it might be that the background thread
            // will update this message quite frequently, and we need
            // to throttle the updates so as not to completely clobber
            // the event dispatching system.
            if (messageUpdate.getAndSet(message) == null) {
                runLater(new Runnable() {
                    @Override
                    public void run() {
                        final String message = messageUpdate.getAndSet(null);
                        Task.this.message.set(message);
                    }
                });
            }
        }
    }

    /**
     * Updates the <code>title</code> property. Calls to updateTitle
     * are coalesced and run later on the FX application thread, so calls
     * to updateTitle, even from the FX Application thread, may not
     * necessarily result in immediate updates to this property, and
     * intermediate title values may be coalesced to save on event
     * notifications.
     * <p>
     *     <em>This method is safe to be called from any thread.</em>
     * </p>
     *
     * @param title the new title
     */
    protected void updateTitle(String title) {
        if (isFxApplicationThread()) {
            this.title.set(title);
        } else {
            // As with the workDone, it might be that the background thread
            // will update this title quite frequently, and we need
            // to throttle the updates so as not to completely clobber
            // the event dispatching system.
            if (titleUpdate.getAndSet(title) == null) {
                runLater(new Runnable() {
                    @Override
                    public void run() {
                        final String title = titleUpdate.getAndSet(null);
                        Task.this.title.set(title);
                    }
                });
            }
        }
    }

    /**
     * Updates the <code>value</code> property. Calls to updateValue
     * are coalesced and run later on the FX application thread, so calls
     * to updateValue, even from the FX Application thread, may not
     * necessarily result in immediate updates to this property, and
     * intermediate values may be coalesced to save on event
     * notifications.
     * <p>
     *     <em>This method is safe to be called from any thread.</em>
     * </p>
     *
     * @param value the new value
     * @since JavaFX 8.0
     */
    protected void updateValue(V value) {
        if (isFxApplicationThread()) {
            this.value.set(value);
        } else {
            // As with the workDone, it might be that the background thread
            // will update this value quite frequently, and we need
            // to throttle the updates so as not to completely clobber
            // the event dispatching system.
            if (valueUpdate.getAndSet(value) == null) {
                runLater(() -> Task.this.value.set(valueUpdate.getAndSet(null)));
            }
        }
    }

    /*
     * IMPLEMENTATION
     */
    private void checkThread() {
        if (started && !isFxApplicationThread()) {
            throw new IllegalStateException("Task must only be used from the FX Application Thread");
        }
    }

    // This method exists for the sake of testing, so I can subclass and override
    // this method in the test and not actually use Platform.runLater.
    void runLater(Runnable r) {
        Platform.runLater(r);
    }

    // This method exists for the sake of testing, so I can subclass and override
    // this method in the test and not actually use Platform.isFxApplicationThread.
    boolean isFxApplicationThread() {
        return Platform.isFxApplicationThread();
    }

    /***************************************************************************
     *                                                                         *
     *                         Event Dispatch                                  *
     *                                                                         *
     **************************************************************************/

    private EventHelper eventHelper = null;

    private EventHelper getEventHelper() {
        if (eventHelper == null) {
            eventHelper = new EventHelper(this);
        }
        return eventHelper;
    }

    /**
     * Registers an event handler to this task. Any event filters are first
     * processed, then the specified onFoo event handlers, and finally any
     * event handlers registered by this method. As with other events
     * in the scene graph, if an event is consumed, it will not continue
     * dispatching.
     *
     * @param <T> the specific event class of the handler
     * @param eventType the type of the events to receive by the handler
     * @param eventHandler the handler to register
     * @throws NullPointerException if the event type or handler is null
     * @since JavaFX 2.1
     */
    public final <T extends Event> void addEventHandler(final EventType<T> eventType,
            final EventHandler<? super T> eventHandler) {
        checkThread();
        getEventHelper().addEventHandler(eventType, eventHandler);
    }

    /**
     * Unregisters a previously registered event handler from this task. One
     * handler might have been registered for different event types, so the
     * caller needs to specify the particular event type from which to
     * unregister the handler.
     *
     * @param <T> the specific event class of the handler
     * @param eventType the event type from which to unregister
     * @param eventHandler the handler to unregister
     * @throws NullPointerException if the event type or handler is null
     * @since JavaFX 2.1
     */
    public final <T extends Event> void removeEventHandler(final EventType<T> eventType,
            final EventHandler<? super T> eventHandler) {
        checkThread();
        getEventHelper().removeEventHandler(eventType, eventHandler);
    }

    /**
     * Registers an event filter to this task. Registered event filters get
     * an event before any associated event handlers.
     *
     * @param <T> the specific event class of the filter
     * @param eventType the type of the events to receive by the filter
     * @param eventFilter the filter to register
     * @throws NullPointerException if the event type or filter is null
     * @since JavaFX 2.1
     */
    public final <T extends Event> void addEventFilter(final EventType<T> eventType,
            final EventHandler<? super T> eventFilter) {
        checkThread();
        getEventHelper().addEventFilter(eventType, eventFilter);
    }

    /**
     * Unregisters a previously registered event filter from this task. One
     * filter might have been registered for different event types, so the
     * caller needs to specify the particular event type from which to
     * unregister the filter.
     *
     * @param <T> the specific event class of the filter
     * @param eventType the event type from which to unregister
     * @param eventFilter the filter to unregister
     * @throws NullPointerException if the event type or filter is null
     * @since JavaFX 2.1
     */
    public final <T extends Event> void removeEventFilter(final EventType<T> eventType,
            final EventHandler<? super T> eventFilter) {
        checkThread();
        getEventHelper().removeEventFilter(eventType, eventFilter);
    }

    /**
     * Sets the handler to use for this event type. There can only be one such
     * handler specified at a time. This handler is guaranteed to be called
     * first. This is used for registering the user-defined onFoo event
     * handlers.
     *
     * @param <T> the specific event class of the handler
     * @param eventType the event type to associate with the given eventHandler
     * @param eventHandler the handler to register, or null to unregister
     * @throws NullPointerException if the event type is null
     * @since JavaFX 2.1
     */
    protected final <T extends Event> void setEventHandler(final EventType<T> eventType,
            final EventHandler<? super T> eventHandler) {
        checkThread();
        getEventHelper().setEventHandler(eventType, eventHandler);
    }

    /**
     * Fires the specified event. Any event filter encountered will
     * be notified and can consume the event. If not consumed by the filters,
     * the event handlers on this task are notified. If these don't consume the
     * event either, then all event handlers are called and can consume the
     * event.
     * <p>
     * This method must be called on the FX user thread.
     *
     * @param event the event to fire
     * @since JavaFX 2.1
     */
    public final void fireEvent(Event event) {
        checkThread();
        getEventHelper().fireEvent(event);
    }

    @Override
    public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
        checkThread();
        return getEventHelper().buildEventDispatchChain(tail);
    }

    /**
     * A struct like class that contains the last workDone update information.
     * What we do when updateProgress is called, is we create a new ProgressUpdate
     * object and store it. If it was null, then we fire off a new Runnable
     * using RunLater, which will eventually read the latest and set it to null
     * atomically. If it was not null, then we simply update it.
     */
    private static final class ProgressUpdate {
        private final double workDone;
        private final double totalWork;

        private ProgressUpdate(double p, double m) {
            this.workDone = p;
            this.totalWork = m;
        }
    }

    /**
     *  TaskCallable actually implements the Callable contract as defined for
     *  the FutureTask class, and is necessary so as to allow us to intercept
     *  the call() operation to update state on the Task as appropriate.
     * @param <V>
     */
    private static final class TaskCallable<V> implements Callable<V> {
        /**
         * The Task that is going to use this TaskCallable
         */
        private Task<V> task;

        /**
         * Create a TaskCallable. The concurrent and other fields MUST be set
         * immediately after creation.
         */
        private TaskCallable() {
        }

        /**
         * Invoked by the system when it is time to run the client code. This
         * implementation is where we modify the state and other properties
         * and from which we invoke the events.
         *
         * @return The result of the Task call method
         * @throws Exception any exception which occurred
         */
        @Override
        public V call() throws Exception {
            // If the Task is sent to an ExecutorService for execution, then we
            // will need to make sure that we transition first to the SCHEDULED
            // state before then transitioning to the RUNNING state. If the
            // Task was executed by a Service, then it will have already been
            // in the SCHEDULED state and setting it again here has no negative
            // effect. But we must ensure that SCHEDULED is visited before RUNNING
            // in all cases so that developer code can be consistent.
            task.started = true;
            task.runLater(() -> {
                task.setState(State.SCHEDULED);
                task.setState(State.RUNNING);
            });
            // Go ahead and delegate to the wrapped callable
            try {
                final V result = task.call();
                if (!task.isCancelled()) {
                    // If it was not cancelled, then we take the return
                    // value and set it as the result.
                    task.runLater(() -> {
                        // The result must be set first, so that when the
                        // SUCCEEDED flag is set, the value will be available
                        // The alternative is not the case, because you
                        // can assume if the result is set, it has
                        // succeeded.
                        task.updateValue(result);
                        task.setState(State.SUCCEEDED);
                    });
                    return result;
                } else {
                    // Since cancelled Future/FutureTask doesn't return any value,
                    // the returned value is going to be trashed, so we can jus return null
                    return null;
                }
            } catch (final Throwable th) {
                // Be sure to set the state after setting the cause of failure
                // so that developers handling the state change events have a
                // throwable to inspect when they get the FAILED state. Note
                // that the other way around is not important -- when a developer
                // observes the causeOfFailure is set to a non-null value, even
                // though the state has not yet been updated, he can infer that
                // it will be FAILED because it can be nothing other than FAILED
                // in that circumstance.
                task.runLater(() -> {
                    task._setException(th);
                    task.setState(State.FAILED);
                });
                // Some error occurred during the call (it might be
                // an exception (either runtime or checked), or it might
                // be an error. In any case, we capture the throwable,
                // record it as the causeOfFailure, and then rethrow. However
                // since the Callable interface requires that we throw an
                // Exception (not Throwable), we have to wrap the exception
                // if it is not already one.
                if (th instanceof Exception) {
                    throw (Exception) th;
                } else {
                    throw new Exception(th);
                }
            }
        }
    }
}