1 /* 2 * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.concurrent; 27 28 import java.security.AccessController; 29 import java.security.Permission; 30 import java.security.PrivilegedAction; 31 import javafx.application.Platform; 32 import javafx.beans.property.BooleanProperty; 33 import javafx.beans.property.DoubleProperty; 34 import javafx.beans.property.ObjectProperty; 35 import javafx.beans.property.ReadOnlyBooleanProperty; 36 import javafx.beans.property.ReadOnlyDoubleProperty; 37 import javafx.beans.property.ReadOnlyObjectProperty; 38 import javafx.beans.property.ReadOnlyStringProperty; 39 import javafx.beans.property.SimpleBooleanProperty; 40 import javafx.beans.property.SimpleDoubleProperty; 41 import javafx.beans.property.SimpleObjectProperty; 42 import javafx.beans.property.SimpleStringProperty; 43 import javafx.beans.property.StringProperty; 44 import javafx.event.Event; 45 import javafx.event.EventDispatchChain; 46 import javafx.event.EventHandler; 47 import javafx.event.EventTarget; 48 import javafx.event.EventType; 49 import java.util.concurrent.Callable; 50 import java.util.concurrent.FutureTask; 51 import java.util.concurrent.atomic.AtomicReference; 52 import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_CANCELLED; 53 import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_FAILED; 54 import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_RUNNING; 55 import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_SCHEDULED; 56 import static javafx.concurrent.WorkerStateEvent.WORKER_STATE_SUCCEEDED; 57 58 /** 59 * <p> 60 * A fully observable implementation of a {@link FutureTask}. {@code Task} exposes 61 * additional state and observable properties useful for programming asynchronous 62 * tasks in JavaFX, as defined in the {@link Worker} interface. An implementation 63 * of Task must override the {@link javafx.concurrent.Task#call()} method. This method 64 * is invoked on the background thread. Any state which is used in this method 65 * must be safe to read and write from a background thread. For example, manipulating 66 * a live scene graph from this method is unsafe and will result in runtime 67 * exceptions. 68 * </p> 69 * <p> 70 * Tasks are flexible and extremely useful for the encapsulation of "work". Because 71 * {@link Service} is designed to execute a Task, any Tasks defined by the application 72 * or library code can easily be used with a Service. Likewise, since Task extends 73 * from FutureTask, it is very easy and natural to use a Task with the java concurrency 74 * {@link java.util.concurrent.Executor} API. Since a Task is Runnable, you 75 * can also call it directly (by invoking the {@link javafx.concurrent.Task#run()} method) 76 * from another background thread. This allows for composition of work, or pass it to 77 * a new Thread constructed and executed manually. Finally, since you can 78 * manually create a new Thread, passing it a Runnable, it is possible to use 79 * the following idiom: 80 * </p> 81 * <pre><code> 82 * Thread th = new Thread(task); 83 * th.setDaemon(true); 84 * th.start(); 85 * </code></pre> 86 * <p> 87 * Note that this code sets the daemon flag of the Thread to true. If you 88 * want a background thread to prevent the VM from existing after the last 89 * stage is closed, then you would want daemon to be false. However, if 90 * you want the background threads to simply terminate after all the 91 * stages are closed, then you must set daemon to true. 92 * </p> 93 * <p> 94 * Although {@link java.util.concurrent.ExecutorService} defines several methods which 95 * take a Runnable, you should generally limit yourself to using the <code>execute</code> 96 * method inherited from {@link java.util.concurrent.Executor}. 97 * </p> 98 * <p> 99 * As with FutureTask, a Task is a one-shot class and cannot be reused. See {@link Service} 100 * for a reusable {@link Worker}. 101 * </p> 102 * <p> 103 * Because the Task is designed for use with JavaFX GUI applications, it ensures 104 * that every change to its public properties, as well as change notifications 105 * for state, errors, and for event handlers, all occur on the main JavaFX application 106 * thread. Accessing these properties from a background thread (including the 107 * {@link #call()} method) will result in runtime exceptions being raised. The only exception 108 * to this, is when initially configuring a Task, which may safely be done 109 * from any thread. However, once the Task has been initialized and 110 * started, it may only thereafter be used from the FX thread (except for those methods clearly 111 * marked as being appropriate for the subclass to invoke from the background thread). 112 * </p> 113 * <p> 114 * It is <strong>strongly encouraged</strong> that all Tasks be initialized with 115 * immutable state upon which the Task will operate. This should be done by providing 116 * a Task constructor which takes the parameters necessary for execution of the Task. 117 * Immutable state makes it easy and safe to use from any thread and ensures 118 * correctness in the presence of multiple threads. 119 * </p> 120 * <p> 121 * In Java there is no reliable way to "kill" a thread in process. However, 122 * when <code>cancel</code> is called on a Task, it is important that 123 * the Task stop processing. A "run-away" Task might continue processing 124 * and updating the message, text, and progress properties even after the 125 * Task has been cancelled! In Java, cancelling a Task is a cooperative 126 * endeavor. The user of the Task will request that it be cancelled, and 127 * the author of the Task must check whether is has been cancelled within 128 * the body of the <code>call</code> method. There are two ways this can 129 * be done. First, the Task author may check the isCancelled method, 130 * inherited from <code>FutureTask</code>, to see whether the Task has 131 * been cancelled. Second, if the Task implementation makes use of any 132 * blocking calls (such as NIO InterruptibleChannels or Thread.sleep) and 133 * the task is cancelled while in such a blocking call, an 134 * InterruptedException is thrown. Task implementations which have blocking 135 * calls should recognize that an interrupted thread may be the signal for 136 * a cancelled task and should double check the isCancelled method to ensure 137 * that the InterruptedException was thrown due to the cancellation of the 138 * Task. 139 * </p> 140 * <h2>Examples</h2> 141 * <p> 142 * The following set of examples demonstrate some of the most common uses of 143 * Tasks. 144 * </p> 145 * 146 * <h3>A Simple Loop</h3> 147 * 148 * <p> 149 * The first example is a simple loop that does nothing particularly useful, 150 * but demonstrates the fundamental aspects of writing a Task correctly. This 151 * example will simply loop and print to standard out on each loop iteration. 152 * When it completes, it returns the number of times it iterated. 153 * </p> 154 * 155 * <pre><code> 156 * Task<Integer> task = new Task<Integer>() { 157 * @Override protected Integer call() throws Exception { 158 * int iterations; 159 * for (iterations = 0; iterations < 100000; iterations++) { 160 * if (isCancelled()) { 161 * break; 162 * } 163 * System.out.println("Iteration " + iterations); 164 * } 165 * return iterations; 166 * } 167 * }; 168 * </code></pre> 169 * 170 * <p> 171 * First, we define what type of value is returned from this Task. In this 172 * case, we want to return the number of times we iterated, so we will 173 * specify the Task to be of type Integer by using generics. Then, within 174 * the implementation of the <code>call</code> method, we iterate from 175 * 0 to 100000. On each iteration, we check to see whether this Task has 176 * been cancelled. If it has been, then we break out of the loop and return 177 * the number of times we iterated. Otherwise a message is printed to 178 * the console and the iteration count increased and we continue looping. 179 * </p> 180 * 181 * <p> 182 * Checking for isCancelled() in the loop body is critical, otherwise the 183 * developer may cancel the task, but the task will continue running 184 * and updating both the progress and returning the incorrect result 185 * from the end of the <code>call</code> method. A correct implementation 186 * of a Task will always check for cancellation. 187 * </p> 188 * 189 * <h3>A Simple Loop With Progress Notification</h3> 190 * 191 * <p> 192 * Similar to the previous example, except this time we will modify the 193 * progress of the Task in each iteration. Note that we have a choice 194 * to make in the case of cancellation. Do we want to set the progress back 195 * to -1 (indeterminate) when the Task is cancelled, or do we want to leave 196 * the progress where it was at? In this case, let's leave the progress alone 197 * and only update the message on cancellation, though updating the 198 * progress after cancellation is a perfectly valid choice. 199 * </p> 200 * 201 * <pre><code> 202 * Task<Integer> task = new Task<Integer>() { 203 * @Override protected Integer call() throws Exception { 204 * int iterations; 205 * for (iterations = 0; iterations < 10000000; iterations++) { 206 * if (isCancelled()) { 207 * updateMessage("Cancelled"); 208 * break; 209 * } 210 * updateMessage("Iteration " + iterations); 211 * updateProgress(iterations, 10000000); 212 * } 213 * return iterations; 214 * } 215 * }; 216 * </code></pre> 217 * 218 * <p> 219 * As before, within the for loop we check whether the Task has been 220 * cancelled. If it has been cancelled, we will update the Task's 221 * message to indicate that it has been cancelled, and then break as 222 * before. If the Task has not been cancelled, then we will update its 223 * message to indicate the current iteration and then update the 224 * progress to indicate the current progress. 225 * </p> 226 * 227 * <h3>A Simple Loop With Progress Notification And Blocking Calls</h3> 228 * 229 * <p> 230 * This example adds to the previous examples a blocking call. Because a 231 * blocking call may thrown an InterruptedException, and because an 232 * InterruptedException may occur as a result of the Task being cancelled, 233 * we need to be sure to handle the InterruptedException and check on the 234 * cancel state. 235 * </p> 236 * 237 * <pre><code> 238 * Task<Integer> task = new Task<Integer>() { 239 * @Override protected Integer call() throws Exception { 240 * int iterations; 241 * for (iterations = 0; iterations < 1000; iterations++) { 242 * if (isCancelled()) { 243 * updateMessage("Cancelled"); 244 * break; 245 * } 246 * updateMessage("Iteration " + iterations); 247 * updateProgress(iterations, 1000); 248 * 249 * // Now block the thread for a short time, but be sure 250 * // to check the interrupted exception for cancellation! 251 * try { 252 * Thread.sleep(100); 253 * } catch (InterruptedException interrupted) { 254 * if (isCancelled()) { 255 * updateMessage("Cancelled"); 256 * break; 257 * } 258 * } 259 * } 260 * return iterations; 261 * } 262 * }; 263 * </code></pre> 264 * 265 * <p> 266 * Here we have added to the body of the loop a <code>Thread.sleep</code> 267 * call. Since this is a blocking call, I have to handle the potential 268 * InterruptedException. Within the catch block, I will check whether 269 * the Task has been cancelled, and if so, update the message accordingly 270 * and break out of the loop. 271 * </p> 272 * 273 * <h3>A Task Which Takes Parameters</h3> 274 * 275 * <p> 276 * Most Tasks require some parameters in order to do useful work. For 277 * example, a DeleteRecordTask needs the object or primary key to delete 278 * from the database. A ReadFileTask needs the URI of the file to be read. 279 * Because Tasks operate on a background thread, care must be taken to 280 * make sure the body of the <code>call</code> method does not read or 281 * modify any shared state. There are two techniques most useful for 282 * doing this: using final variables, and passing variables to a Task 283 * during construction. 284 * </p> 285 * 286 * <p> 287 * When using a Task as an anonymous class, the most natural way to pass 288 * parameters to the Task is by using final variables. In this example, 289 * we pass to the Task the total number of times the Task should iterate. 290 * </p> 291 * 292 * <pre><code> 293 * final int totalIterations = 9000000; 294 * Task<Integer> task = new Task<Integer>() { 295 * @Override protected Integer call() throws Exception { 296 * int iterations; 297 * for (iterations = 0; iterations < totalIterations; iterations++) { 298 * if (isCancelled()) { 299 * updateMessage("Cancelled"); 300 * break; 301 * } 302 * updateMessage("Iteration " + iterations); 303 * updateProgress(iterations, totalIterations); 304 * } 305 * return iterations; 306 * } 307 * }; 308 * </code></pre> 309 * 310 * <p> 311 * Since <code>totalIterations</code> is final, the <code>call</code> 312 * method can safely read it and refer to it from a background thread. 313 * </p> 314 * 315 * <p> 316 * When writing Task libraries (as opposed to specific-use implementations), 317 * we need to use a different technique. In this case, I will create an 318 * IteratingTask which performs the same work as above. This time, since 319 * the IteratingTask is defined in its own file, it will need to have 320 * parameters passed to it in its constructor. These parameters are 321 * assigned to final variables. 322 * </p> 323 * 324 * <pre><code> 325 * public class IteratingTask extends Task<Integer> { 326 * private final int totalIterations; 327 * 328 * public IteratingTask(int totalIterations) { 329 * this.totalIterations = totalIterations; 330 * } 331 * 332 * @Override protected Integer call() throws Exception { 333 * int iterations = 0; 334 * for (iterations = 0; iterations < totalIterations; iterations++) { 335 * if (isCancelled()) { 336 * updateMessage("Cancelled"); 337 * break; 338 * } 339 * updateMessage("Iteration " + iterations); 340 * updateProgress(iterations, totalIterations); 341 * } 342 * return iterations; 343 * } 344 * } 345 * </code></pre> 346 * 347 * <p>And then when used:</p> 348 * 349 * <pre><code> 350 * IteratingTask task = new IteratingTask(8000000); 351 * </code></pre> 352 * 353 * <p>In this way, parameters are passed to the IteratingTask in a safe 354 * manner, and again, are final. Thus, the <code>call</code> method can 355 * safely read this state from a background thread.</p> 356 * 357 * <p>WARNING: Do not pass mutable state to a Task and then operate on it 358 * from a background thread. Doing so may introduce race conditions. In 359 * particular, suppose you had a SaveCustomerTask which took a Customer 360 * in its constructor. Although the SaveCustomerTask may have a final 361 * reference to the Customer, if the Customer object is mutable, then it 362 * is possible that both the SaveCustomerTask and some other application code 363 * will be reading or modifying the state of the Customer from different 364 * threads. Be very careful in such cases, that while a mutable object such 365 * as this Customer is being used from a background thread, that it is 366 * not being used also from another thread. In particular, if the background 367 * thread is reading data from the database and updating the Customer object, 368 * and the Customer object is bound to scene graph nodes (such as UI 369 * controls), then there could be a violation of threading rules! For such 370 * cases, modify the Customer object from the FX Application Thread rather 371 * than from the background thread.</p> 372 * 373 * <pre><code> 374 * public class UpdateCustomerTask extends Task<Customer> { 375 * private final Customer customer; 376 * 377 * public UpdateCustomerTask(Customer customer) { 378 * this.customer = customer; 379 * } 380 * 381 * @Override protected Customer call() throws Exception { 382 * // pseudo-code: 383 * // query the database 384 * // read the values 385 * 386 * // Now update the customer 387 * Platform.runLater(new Runnable() { 388 * @Override public void run() { 389 * customer.setFirstName(rs.getString("FirstName")); 390 * // etc 391 * } 392 * }); 393 * 394 * return customer; 395 * } 396 * } 397 * </code></pre> 398 * 399 * <h3>A Task Which Returns No Value</h3> 400 * 401 * <p> 402 * Many, if not most, Tasks should return a value upon completion. For 403 * CRUD Tasks, one would expect that a "Create" Task would return the newly 404 * created object or primary key, a "Read" Task would return the read 405 * object, an "Update" task would return the number of records updated, 406 * and a "Delete" task would return the number of records deleted. 407 * </p> 408 * 409 * <p> 410 * However sometimes there just isn't anything truly useful to return. 411 * For example, I might have a Task which writes to a file. Task has built 412 * into it a mechanism for indicating whether it has succeeded or failed 413 * along with the number of bytes written (the progress), and thus there is 414 * nothing really for me to return. In such a case, you can use the Void 415 * type. This is a special type in the Java language which can only be 416 * assigned the value of <code>null</code>. You would use it as follows: 417 * </p> 418 * 419 * <pre><code> 420 * final String filePath = "/foo.txt"; 421 * final String contents = "Some contents"; 422 * Task<Void> task = new Task<Void>() { 423 * @Override protected Void call() throws Exception { 424 * File file = new File(filePath); 425 * FileOutputStream out = new FileOutputStream(file); 426 * // ... and other code to write the contents ... 427 * 428 * // Return null at the end of a Task of type Void 429 * return null; 430 * } 431 * }; 432 * </code></pre> 433 * 434 * <h3>A Task Which Returns An ObservableList</h3> 435 * 436 * <p>Because the ListView, TableView, and other UI controls and scene graph 437 * nodes make use of ObservableList, it is common to want to create and return 438 * an ObservableList from a Task. When you do not care to display intermediate 439 * values, the easiest way to correctly write such a Task is simply to 440 * construct an ObservableList within the <code>call</code> method, and then 441 * return it at the conclusion of the Task.</p> 442 * 443 * <pre><code> 444 * Task<ObservableList<Rectangle>> task = new Task<ObservableList<Rectangle>>() { 445 * @Override protected ObservableList<Rectangle> call() throws Exception { 446 * updateMessage("Creating Rectangles"); 447 * ObservableList<Rectangle> results = FXCollections.observableArrayList(); 448 * for (int i=0; i<100; i++) { 449 * if (isCancelled()) break; 450 * Rectangle r = new Rectangle(10, 10); 451 * r.setX(10 * i); 452 * results.add(r); 453 * updateProgress(i, 100); 454 * } 455 * return results; 456 * } 457 * }; 458 * </code></pre> 459 * 460 * <p>In the above example, we are going to create 100 rectangles and return 461 * them from this task. An ObservableList is created within the 462 * <code>call</code> method, populated, and then returned.</p> 463 * 464 * <h3>A Task Which Returns Partial Results</h3> 465 * 466 * <p>Sometimes you want to create a Task which will return partial results. 467 * Perhaps you are building a complex scene graph and want to show the 468 * scene graph as it is being constructed. Or perhaps you are reading a large 469 * amount of data over the network and want to display the entries in a 470 * TableView as the data is arriving. In such cases, there is some shared state 471 * available both to the FX Application Thread and the background thread. 472 * Great care must be taken to <strong>never update shared state from any 473 * thread other than the FX Application Thread</strong>.</p> 474 * 475 * <p>The easiest way to do this is to take advantage of the {@link #updateValue(Object)} method. 476 * This method may be called repeatedly from the background thread. Updates are coalesced to 477 * prevent saturation of the FX event queue. This means you can call it as frequently as 478 * you like from the background thread but only the most recent set is ultimately set.</p> 479 * 480 * <pre><code> 481 * Task<Long> task = new Task<Long>() { 482 * @Override protected Long call() throws Exception { 483 * long a=0; 484 * long b=1; 485 * for (long i = 0; i < Long.MAX_VALUE; i++){ 486 * updateValue(a); 487 * a += b; 488 * b = a - b; 489 * } 490 * return a; 491 * } 492 * }; 493 * </code></pre> 494 * 495 * <p>Another way to do this is to expose a new property on the Task 496 * which will represent the partial result. Then make sure to use 497 * <code>Platform.runLater</code> when updating the partial result.</p> 498 * 499 * <pre><code> 500 * Task<Long> task = new Task<Long>() { 501 * @Override protected Long call() throws Exception { 502 * long a=0; 503 * long b=1; 504 * for (long i = 0; i < Long.MAX_VALUE; i++){ 505 * final long v = a; 506 * Platform.runLater(new Runnable() { 507 * @Override public void run() { 508 * updateValue(v); 509 * } 510 * } 511 * a += b; 512 * b = a - b; 513 * } 514 * return a; 515 * } 516 * }; 517 * </code></pre> 518 * 519 * <p>Suppose instead of updating a single value, you want to populate an ObservableList 520 * with results as they are obtained. One approach is to expose a new property on the Task 521 * which will represent the partial result. Then make sure to use 522 * <code>Platform.runLater</code> when adding new items to the partial 523 * result.</p> 524 * 525 * <pre><code> 526 * public class PartialResultsTask extends Task<ObservableList<Rectangle>> { 527 * // Uses Java 7 diamond operator 528 * private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults = 529 * new ReadOnlyObjectWrapper<>(this, "partialResults", 530 * FXCollections.observableArrayList(new ArrayList<Rectangle>())); 531 * 532 * public final ObservableList<Rectangle> getPartialResults() { return partialResults.get(); } 533 * public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty() { 534 * return partialResults.getReadOnlyProperty(); 535 * } 536 * 537 * @Override protected ObservableList<Rectangle> call() throws Exception { 538 * updateMessage("Creating Rectangles..."); 539 * for (int i=0; i<100; i++) { 540 * if (isCancelled()) break; 541 * final Rectangle r = new Rectangle(10, 10); 542 * r.setX(10 * i); 543 * Platform.runLater(new Runnable() { 544 * @Override public void run() { 545 * partialResults.get().add(r); 546 * } 547 * }); 548 * updateProgress(i, 100); 549 * } 550 * return partialResults.get(); 551 * } 552 * } 553 * </code></pre> 554 * 555 * <h3>A Task Which Modifies The Scene Graph</h3> 556 * 557 * <p>Generally, Tasks should not interact directly with the UI. Doing so 558 * creates a tight coupling between a specific Task implementation and a 559 * specific part of your UI. However, when you do want to create such a 560 * coupling, you must ensure that you use <code>Platform.runLater</code> 561 * so that any modifications of the scene graph occur on the 562 * FX Application Thread.</p> 563 * 564 * <pre><code> 565 * final Group group = new Group(); 566 * Task<Void> task = new Task<Void>() { 567 * @Override protected Void call() throws Exception { 568 * for (int i=0; i<100; i++) { 569 * if (isCancelled()) break; 570 * final Rectangle r = new Rectangle(10, 10); 571 * r.setX(10 * i); 572 * Platform.runLater(new Runnable() { 573 * @Override public void run() { 574 * group.getChildren().add(r); 575 * } 576 * }); 577 * } 578 * return null; 579 * } 580 * }; 581 * </code></pre> 582 * 583 * <h3>Reacting To State Changes Generically</h3> 584 * 585 * <p>Sometimes you may want to write a Task which updates its progress, 586 * message, text, or in some other way reacts whenever a state change 587 * happens on the Task. For example, you may want to change the status 588 * message on the Task on Failure, Success, Running, or Cancelled state changes. 589 * </p> 590 * <pre><code> 591 * Task<Integer> task = new Task<Integer>() { 592 * @Override protected Integer call() throws Exception { 593 * int iterations = 0; 594 * for (iterations = 0; iterations < 100000; iterations++) { 595 * if (isCancelled()) { 596 * break; 597 * } 598 * System.out.println("Iteration " + iterations); 599 * } 600 * return iterations; 601 * } 602 * 603 * @Override protected void succeeded() { 604 * super.succeeded(); 605 * updateMessage("Done!"); 606 * } 607 * 608 * @Override protected void cancelled() { 609 * super.cancelled(); 610 * updateMessage("Cancelled!"); 611 * } 612 * 613 * @Override protected void failed() { 614 * super.failed(); 615 * updateMessage("Failed!"); 616 * } 617 * }; 618 * </code></pre> 619 * @since JavaFX 2.0 620 */ 621 public abstract class Task<V> extends FutureTask<V> implements Worker<V>, EventTarget { 622 /** 623 * Used to send workDone updates in a thread-safe manner from the subclass 624 * to the FX application thread and workDone related properties. AtomicReference 625 * is used so as to coalesce updates such that we don't flood the event queue. 626 */ 627 private AtomicReference<ProgressUpdate> progressUpdate = new AtomicReference<>(); 628 629 /** 630 * Used to send message updates in a thread-safe manner from the subclass 631 * to the FX application thread. AtomicReference is used so as to coalesce 632 * updates such that we don't flood the event queue. 633 */ 634 private AtomicReference<String> messageUpdate = new AtomicReference<>(); 635 636 /** 637 * Used to send title updates in a thread-safe manner from the subclass 638 * to the FX application thread. AtomicReference is used so as to coalesce 639 * updates such that we don't flood the event queue. 640 */ 641 private AtomicReference<String> titleUpdate = new AtomicReference<>(); 642 643 /** 644 * Used to send value updates in a thread-safe manner from the subclass 645 * to the FX application thread. AtomicReference is used so as to coalesce 646 * updates such that we don't flood the event queue. 647 */ 648 private AtomicReference<V> valueUpdate = new AtomicReference<>(); 649 650 /** 651 * This is used so we have a thread-safe way to ask whether the task was 652 * started in the checkThread() method. 653 */ 654 private volatile boolean started = false; 655 656 /** 657 * Creates a new Task. 658 */ 659 public Task() { 660 this(new TaskCallable<V>()); 661 } 662 663 /** 664 * This bit of construction trickery is necessary because otherwise there is 665 * no way for the main constructor to both create the callable and maintain 666 * a reference to it, which is necessary because an anonymous callable construction 667 * cannot reference the implicit "this". We leverage an internal Callable 668 * so that all the pre-built semantics around cancel and so forth are 669 * handled correctly. 670 * 671 * @param callableAdapter non-null implementation of the 672 * TaskCallable adapter 673 */ 674 private Task(final TaskCallable<V> callableAdapter) { 675 super(callableAdapter); 676 callableAdapter.task = this; 677 } 678 679 /** 680 * Invoked when the Task is executed, the call method must be overridden and 681 * implemented by subclasses. The call method actually performs the 682 * background thread logic. Only the updateProgress, updateMessage, updateValue and 683 * updateTitle methods of Task may be called from code within this method. 684 * Any other interaction with the Task from the background thread will result 685 * in runtime exceptions. 686 * 687 * @return The result of the background work, if any. 688 * @throws Exception an unhandled exception which occurred during the 689 * background operation 690 */ 691 protected abstract V call() throws Exception; 692 693 private ObjectProperty<State> state = new SimpleObjectProperty<>(this, "state", State.READY); 694 final void setState(State value) { // package access for the Service 695 checkThread(); 696 final State s = getState(); 697 if (s != State.CANCELLED) { 698 this.state.set(value); 699 // Make sure the running flag is set 700 setRunning(value == State.SCHEDULED || value == State.RUNNING); 701 702 // Invoke the event handlers, and then call the protected methods. 703 switch (state.get()) { 704 case CANCELLED: 705 fireEvent(new WorkerStateEvent(this, WORKER_STATE_CANCELLED)); 706 cancelled(); 707 break; 708 case FAILED: 709 fireEvent(new WorkerStateEvent(this, WORKER_STATE_FAILED)); 710 failed(); 711 break; 712 case READY: 713 // This even can never meaningfully occur, because the 714 // Task begins life as ready and can never go back to it! 715 break; 716 case RUNNING: 717 fireEvent(new WorkerStateEvent(this, WORKER_STATE_RUNNING)); 718 running(); 719 break; 720 case SCHEDULED: 721 fireEvent(new WorkerStateEvent(this, WORKER_STATE_SCHEDULED)); 722 scheduled(); 723 break; 724 case SUCCEEDED: 725 fireEvent(new WorkerStateEvent(this, WORKER_STATE_SUCCEEDED)); 726 succeeded(); 727 break; 728 default: throw new AssertionError("Should be unreachable"); 729 } 730 } 731 } 732 @Override public final State getState() { checkThread(); return state.get(); } 733 @Override public final ReadOnlyObjectProperty<State> stateProperty() { checkThread(); return state; } 734 735 /** 736 * The onSchedule event handler is called whenever the Task state 737 * transitions to the SCHEDULED state. 738 * 739 * @return the onScheduled event handler property 740 * @since JavaFX 2.1 741 */ 742 public final ObjectProperty<EventHandler<WorkerStateEvent>> onScheduledProperty() { 743 checkThread(); 744 return getEventHelper().onScheduledProperty(); 745 } 746 747 /** 748 * The onSchedule event handler is called whenever the Task state 749 * transitions to the SCHEDULED state. 750 * 751 * @return the onScheduled event handler, if any 752 * @since JavaFX 2.1 753 */ 754 public final EventHandler<WorkerStateEvent> getOnScheduled() { 755 checkThread(); 756 return eventHelper == null ? null : eventHelper.getOnScheduled(); 757 } 758 759 /** 760 * The onSchedule event handler is called whenever the Task state 761 * transitions to the SCHEDULED state. 762 * 763 * @param value the event handler, can be null to clear it 764 * @since JavaFX 2.1 765 */ 766 public final void setOnScheduled(EventHandler<WorkerStateEvent> value) { 767 checkThread(); 768 getEventHelper().setOnScheduled(value); 769 } 770 771 /** 772 * A protected convenience method for subclasses, called whenever the 773 * state of the Task has transitioned to the SCHEDULED state. 774 * This method is invoked on the FX Application Thread after the Task has been fully transitioned to 775 * the new state. 776 * @since JavaFX 2.1 777 */ 778 protected void scheduled() { } 779 780 /** 781 * The onRunning event handler is called whenever the Task state 782 * transitions to the RUNNING state. 783 * 784 * @return the onRunning event handler property 785 * @since JavaFX 2.1 786 */ 787 public final ObjectProperty<EventHandler<WorkerStateEvent>> onRunningProperty() { 788 checkThread(); 789 return getEventHelper().onRunningProperty(); 790 } 791 792 /** 793 * The onRunning event handler is called whenever the Task state 794 * transitions to the RUNNING state. 795 * 796 * @return the onRunning event handler, if any 797 * @since JavaFX 2.1 798 */ 799 public final EventHandler<WorkerStateEvent> getOnRunning() { 800 checkThread(); 801 return eventHelper == null ? null : eventHelper.getOnRunning(); 802 } 803 804 /** 805 * The onRunning event handler is called whenever the Task state 806 * transitions to the RUNNING state. 807 * 808 * @param value the event handler, can be null to clear it 809 * @since JavaFX 2.1 810 */ 811 public final void setOnRunning(EventHandler<WorkerStateEvent> value) { 812 checkThread(); 813 getEventHelper().setOnRunning(value); 814 } 815 816 /** 817 * A protected convenience method for subclasses, called whenever the 818 * state of the Task has transitioned to the RUNNING state. 819 * This method is invoked on the FX Application Thread after the Task has been fully transitioned to 820 * the new state. 821 * @since JavaFX 2.1 822 */ 823 protected void running() { } 824 825 /** 826 * The onSucceeded event handler is called whenever the Task state 827 * transitions to the SUCCEEDED state. 828 * 829 * @return the onSucceeded event handler property 830 * @since JavaFX 2.1 831 */ 832 public final ObjectProperty<EventHandler<WorkerStateEvent>> onSucceededProperty() { 833 checkThread(); 834 return getEventHelper().onSucceededProperty(); 835 } 836 837 /** 838 * The onSucceeded event handler is called whenever the Task state 839 * transitions to the SUCCEEDED state. 840 * 841 * @return the onSucceeded event handler, if any 842 * @since JavaFX 2.1 843 */ 844 public final EventHandler<WorkerStateEvent> getOnSucceeded() { 845 checkThread(); 846 return eventHelper == null ? null : eventHelper.getOnSucceeded(); 847 } 848 849 /** 850 * The onSucceeded event handler is called whenever the Task state 851 * transitions to the SUCCEEDED state. 852 * 853 * @param value the event handler, can be null to clear it 854 * @since JavaFX 2.1 855 */ 856 public final void setOnSucceeded(EventHandler<WorkerStateEvent> value) { 857 checkThread(); 858 getEventHelper().setOnSucceeded(value); 859 } 860 861 /** 862 * A protected convenience method for subclasses, called whenever the 863 * state of the Task has transitioned to the SUCCEEDED state. 864 * This method is invoked on the FX Application Thread after the Task has been fully transitioned to 865 * the new state. 866 * @since JavaFX 2.1 867 */ 868 protected void succeeded() { } 869 870 /** 871 * The onCancelled event handler is called whenever the Task state 872 * transitions to the CANCELLED state. 873 * 874 * @return the onCancelled event handler property 875 * @since JavaFX 2.1 876 */ 877 public final ObjectProperty<EventHandler<WorkerStateEvent>> onCancelledProperty() { 878 checkThread(); 879 return getEventHelper().onCancelledProperty(); 880 } 881 882 /** 883 * The onCancelled event handler is called whenever the Task state 884 * transitions to the CANCELLED state. 885 * 886 * @return the onCancelled event handler, if any 887 * @since JavaFX 2.1 888 */ 889 public final EventHandler<WorkerStateEvent> getOnCancelled() { 890 checkThread(); 891 return eventHelper == null ? null : eventHelper.getOnCancelled(); 892 } 893 894 /** 895 * The onCancelled event handler is called whenever the Task state 896 * transitions to the CANCELLED state. 897 * 898 * @param value the event handler, can be null to clear it 899 * @since JavaFX 2.1 900 */ 901 public final void setOnCancelled(EventHandler<WorkerStateEvent> value) { 902 checkThread(); 903 getEventHelper().setOnCancelled(value); 904 } 905 906 /** 907 * A protected convenience method for subclasses, called whenever the 908 * state of the Task has transitioned to the CANCELLED state. 909 * This method is invoked on the FX Application Thread after the Task has been fully transitioned to 910 * the new state. 911 * @since JavaFX 2.1 912 */ 913 protected void cancelled() { } 914 915 /** 916 * The onFailed event handler is called whenever the Task state 917 * transitions to the FAILED state. 918 * 919 * @return the onFailed event handler property 920 * @since JavaFX 2.1 921 */ 922 public final ObjectProperty<EventHandler<WorkerStateEvent>> onFailedProperty() { 923 checkThread(); 924 return getEventHelper().onFailedProperty(); 925 } 926 927 /** 928 * The onFailed event handler is called whenever the Task state 929 * transitions to the FAILED state. 930 * 931 * @return the onFailed event handler, if any 932 * @since JavaFX 2.1 933 */ 934 public final EventHandler<WorkerStateEvent> getOnFailed() { 935 checkThread(); 936 return eventHelper == null ? null : eventHelper.getOnFailed(); 937 } 938 939 /** 940 * The onFailed event handler is called whenever the Task state 941 * transitions to the FAILED state. 942 * 943 * @param value the event handler, can be null to clear it 944 * @since JavaFX 2.1 945 */ 946 public final void setOnFailed(EventHandler<WorkerStateEvent> value) { 947 checkThread(); 948 getEventHelper().setOnFailed(value); 949 } 950 951 /** 952 * A protected convenience method for subclasses, called whenever the 953 * state of the Task has transitioned to the FAILED state. 954 * This method is invoked on the FX Application Thread after the Task has been fully transitioned to 955 * the new state. 956 * @since JavaFX 2.1 957 */ 958 protected void failed() { } 959 960 private final ObjectProperty<V> value = new SimpleObjectProperty<>(this, "value"); 961 private void setValue(V v) { checkThread(); value.set(v); } 962 @Override public final V getValue() { checkThread(); return value.get(); } 963 @Override public final ReadOnlyObjectProperty<V> valueProperty() { checkThread(); return value; } 964 965 private final ObjectProperty<Throwable> exception = new SimpleObjectProperty<>(this, "exception"); 966 private void _setException(Throwable value) { checkThread(); exception.set(value); } 967 @Override public final Throwable getException() { checkThread(); return exception.get(); } 968 @Override public final ReadOnlyObjectProperty<Throwable> exceptionProperty() { checkThread(); return exception; } 969 970 private final DoubleProperty workDone = new SimpleDoubleProperty(this, "workDone", -1); 971 private void setWorkDone(double value) { checkThread(); workDone.set(value); } 972 @Override public final double getWorkDone() { checkThread(); return workDone.get(); } 973 @Override public final ReadOnlyDoubleProperty workDoneProperty() { checkThread(); return workDone; } 974 975 private final DoubleProperty totalWork = new SimpleDoubleProperty(this, "totalWork", -1); 976 private void setTotalWork(double value) { checkThread(); totalWork.set(value); } 977 @Override public final double getTotalWork() { checkThread(); return totalWork.get(); } 978 @Override public final ReadOnlyDoubleProperty totalWorkProperty() { checkThread(); return totalWork; } 979 980 private final DoubleProperty progress = new SimpleDoubleProperty(this, "progress", -1); 981 private void setProgress(double value) { checkThread(); progress.set(value); } 982 @Override public final double getProgress() { checkThread(); return progress.get(); } 983 @Override public final ReadOnlyDoubleProperty progressProperty() { checkThread(); return progress; } 984 985 private final BooleanProperty running = new SimpleBooleanProperty(this, "running", false); 986 private void setRunning(boolean value) { checkThread(); running.set(value); } 987 @Override public final boolean isRunning() { checkThread(); return running.get(); } 988 @Override public final ReadOnlyBooleanProperty runningProperty() { checkThread(); return running; } 989 990 private final StringProperty message = new SimpleStringProperty(this, "message", ""); 991 @Override public final String getMessage() { checkThread(); return message.get(); } 992 @Override public final ReadOnlyStringProperty messageProperty() { checkThread(); return message; } 993 994 private final StringProperty title = new SimpleStringProperty(this, "title", ""); 995 @Override public final String getTitle() { checkThread(); return title.get(); } 996 @Override public final ReadOnlyStringProperty titleProperty() { checkThread(); return title; } 997 998 @Override public final boolean cancel() { 999 return cancel(true); 1000 } 1001 1002 // Need to assert the modifyThread permission so an app can cancel 1003 // a task that it created (the default executor for the service runs in 1004 // its own thread group) 1005 // Note that this is needed when running as an applet or a web start app. 1006 private static final Permission modifyThreadPerm = new RuntimePermission("modifyThread"); 1007 1008 @Override public boolean cancel(boolean mayInterruptIfRunning) { 1009 // Delegate to the super implementation to actually attempt to cancel this thing 1010 // Assert the modifyThread permission 1011 boolean flag = AccessController.doPrivileged( 1012 (PrivilegedAction<Boolean>) () -> super.cancel(mayInterruptIfRunning), 1013 null, 1014 modifyThreadPerm); 1015 1016 // If cancel succeeded (according to the semantics of the Future cancel method), 1017 // then we need to make sure the State flag is set appropriately 1018 if (flag) { 1019 // If this method was called on the FX application thread, then we can 1020 // just update the state directly and this will make sure that after 1021 // the cancel method was called, the state will be set correctly 1022 // (otherwise it would be indeterminate). However if the cancel method was 1023 // called off the FX app thread, then we must use runLater, and the 1024 // state flag will not be readable immediately after this call. However, 1025 // that would be the case anyway since these properties are not thread-safe. 1026 if (isFxApplicationThread()) { 1027 setState(State.CANCELLED); 1028 } else { 1029 runLater(() -> setState(State.CANCELLED)); 1030 } 1031 } 1032 // return the flag 1033 return flag; 1034 } 1035 1036 /** 1037 * Updates the <code>workDone</code>, <code>totalWork</code>, 1038 * and <code>progress</code> properties. Calls to updateProgress 1039 * are coalesced and run later on the FX application thread, and calls 1040 * to updateProgress, even from the FX Application thread, may not 1041 * necessarily result in immediate updates to these properties, and 1042 * intermediate workDone values may be coalesced to save on event 1043 * notifications. <code>max</code> becomes the new value for 1044 * <code>totalWork</code>. 1045 * <p> 1046 * <em>This method is safe to be called from any thread.</em> 1047 * </p> 1048 * 1049 * @param workDone A value from Long.MIN_VALUE up to max. If the value is greater 1050 * than max, then it will be clamped at max. 1051 * If the value passed is negative then the resulting percent 1052 * done will be -1 (thus, indeterminate). 1053 * @param max A value from Long.MIN_VALUE to Long.MAX_VALUE. 1054 * @see #updateProgress(double, double) 1055 */ 1056 protected void updateProgress(long workDone, long max) { 1057 updateProgress((double)workDone, (double)max); 1058 } 1059 1060 /** 1061 * Updates the <code>workDone</code>, <code>totalWork</code>, 1062 * and <code>progress</code> properties. Calls to updateProgress 1063 * are coalesced and run later on the FX application thread, and calls 1064 * to updateProgress, even from the FX Application thread, may not 1065 * necessarily result in immediate updates to these properties, and 1066 * intermediate workDone values may be coalesced to save on event 1067 * notifications. <code>max</code> becomes the new value for 1068 * <code>totalWork</code>. 1069 * <p> 1070 * <em>This method is safe to be called from any thread.</em> 1071 * </p> 1072 * 1073 * @param workDone A value from Double.MIN_VALUE up to max. If the value is greater 1074 * than max, then it will be clamped at max. 1075 * If the value passed is negative, or Infinity, or NaN, 1076 * then the resulting percentDone will be -1 (thus, indeterminate). 1077 * @param max A value from Double.MIN_VALUE to Double.MAX_VALUE. Infinity and NaN are treated as -1. 1078 * @since JavaFX 2.2 1079 */ 1080 protected void updateProgress(double workDone, double max) { 1081 // Adjust Infinity / NaN to be -1 for both workDone and max. 1082 if (Double.isInfinite(workDone) || Double.isNaN(workDone)) { 1083 workDone = -1; 1084 } 1085 1086 if (Double.isInfinite(max) || Double.isNaN(max)) { 1087 max = -1; 1088 } 1089 1090 if (workDone < 0) { 1091 workDone = -1; 1092 } 1093 1094 if (max < 0) { 1095 max = -1; 1096 } 1097 1098 // Clamp the workDone if necessary so as not to exceed max 1099 if (workDone > max) { 1100 workDone = max; 1101 } 1102 1103 if (isFxApplicationThread()) { 1104 _updateProgress(workDone, max); 1105 } else if (progressUpdate.getAndSet(new ProgressUpdate(workDone, max)) == null) { 1106 runLater(() -> { 1107 final ProgressUpdate update = progressUpdate.getAndSet(null); 1108 _updateProgress(update.workDone, update.totalWork); 1109 }); 1110 } 1111 } 1112 1113 private void _updateProgress(double workDone, double max) { 1114 setTotalWork(max); 1115 setWorkDone(workDone); 1116 if (workDone == -1) { 1117 setProgress(-1); 1118 } else { 1119 setProgress(workDone / max); 1120 } 1121 } 1122 1123 /** 1124 * Updates the <code>message</code> property. Calls to updateMessage 1125 * are coalesced and run later on the FX application thread, so calls 1126 * to updateMessage, even from the FX Application thread, may not 1127 * necessarily result in immediate updates to this property, and 1128 * intermediate message values may be coalesced to save on event 1129 * notifications. 1130 * <p> 1131 * <em>This method is safe to be called from any thread.</em> 1132 * </p> 1133 * 1134 * @param message the new message 1135 */ 1136 protected void updateMessage(String message) { 1137 if (isFxApplicationThread()) { 1138 this.message.set(message); 1139 } else { 1140 // As with the workDone, it might be that the background thread 1141 // will update this message quite frequently, and we need 1142 // to throttle the updates so as not to completely clobber 1143 // the event dispatching system. 1144 if (messageUpdate.getAndSet(message) == null) { 1145 runLater(new Runnable() { 1146 @Override public void run() { 1147 final String message = messageUpdate.getAndSet(null); 1148 Task.this.message.set(message); 1149 } 1150 }); 1151 } 1152 } 1153 } 1154 1155 /** 1156 * Updates the <code>title</code> property. Calls to updateTitle 1157 * are coalesced and run later on the FX application thread, so calls 1158 * to updateTitle, even from the FX Application thread, may not 1159 * necessarily result in immediate updates to this property, and 1160 * intermediate title values may be coalesced to save on event 1161 * notifications. 1162 * <p> 1163 * <em>This method is safe to be called from any thread.</em> 1164 * </p> 1165 * 1166 * @param title the new title 1167 */ 1168 protected void updateTitle(String title) { 1169 if (isFxApplicationThread()) { 1170 this.title.set(title); 1171 } else { 1172 // As with the workDone, it might be that the background thread 1173 // will update this title quite frequently, and we need 1174 // to throttle the updates so as not to completely clobber 1175 // the event dispatching system. 1176 if (titleUpdate.getAndSet(title) == null) { 1177 runLater(new Runnable() { 1178 @Override public void run() { 1179 final String title = titleUpdate.getAndSet(null); 1180 Task.this.title.set(title); 1181 } 1182 }); 1183 } 1184 } 1185 } 1186 1187 /** 1188 * Updates the <code>value</code> property. Calls to updateValue 1189 * are coalesced and run later on the FX application thread, so calls 1190 * to updateValue, even from the FX Application thread, may not 1191 * necessarily result in immediate updates to this property, and 1192 * intermediate values may be coalesced to save on event 1193 * notifications. 1194 * <p> 1195 * <em>This method is safe to be called from any thread.</em> 1196 * </p> 1197 * 1198 * @param value the new value 1199 * @since JavaFX 8.0 1200 */ 1201 protected void updateValue(V value) { 1202 if (isFxApplicationThread()) { 1203 this.value.set(value); 1204 } else { 1205 // As with the workDone, it might be that the background thread 1206 // will update this value quite frequently, and we need 1207 // to throttle the updates so as not to completely clobber 1208 // the event dispatching system. 1209 if (valueUpdate.getAndSet(value) == null) { 1210 runLater(() -> Task.this.value.set(valueUpdate.getAndSet(null))); 1211 } 1212 } 1213 } 1214 1215 /* 1216 * IMPLEMENTATION 1217 */ 1218 private void checkThread() { 1219 if (started && !isFxApplicationThread()) { 1220 throw new IllegalStateException("Task must only be used from the FX Application Thread"); 1221 } 1222 } 1223 1224 // This method exists for the sake of testing, so I can subclass and override 1225 // this method in the test and not actually use Platform.runLater. 1226 void runLater(Runnable r) { 1227 Platform.runLater(r); 1228 } 1229 1230 // This method exists for the sake of testing, so I can subclass and override 1231 // this method in the test and not actually use Platform.isFxApplicationThread. 1232 boolean isFxApplicationThread() { 1233 return Platform.isFxApplicationThread(); 1234 } 1235 1236 /*************************************************************************** 1237 * * 1238 * Event Dispatch * 1239 * * 1240 **************************************************************************/ 1241 1242 private EventHelper eventHelper = null; 1243 private EventHelper getEventHelper() { 1244 if (eventHelper == null) { 1245 eventHelper = new EventHelper(this); 1246 } 1247 return eventHelper; 1248 } 1249 1250 /** 1251 * Registers an event handler to this task. Any event filters are first 1252 * processed, then the specified onFoo event handlers, and finally any 1253 * event handlers registered by this method. As with other events 1254 * in the scene graph, if an event is consumed, it will not continue 1255 * dispatching. 1256 * 1257 * @param <T> the specific event class of the handler 1258 * @param eventType the type of the events to receive by the handler 1259 * @param eventHandler the handler to register 1260 * @throws NullPointerException if the event type or handler is null 1261 * @since JavaFX 2.1 1262 */ 1263 public final <T extends Event> void addEventHandler( 1264 final EventType<T> eventType, 1265 final EventHandler<? super T> eventHandler) { 1266 checkThread(); 1267 getEventHelper().addEventHandler(eventType, eventHandler); 1268 } 1269 1270 /** 1271 * Unregisters a previously registered event handler from this task. One 1272 * handler might have been registered for different event types, so the 1273 * caller needs to specify the particular event type from which to 1274 * unregister the handler. 1275 * 1276 * @param <T> the specific event class of the handler 1277 * @param eventType the event type from which to unregister 1278 * @param eventHandler the handler to unregister 1279 * @throws NullPointerException if the event type or handler is null 1280 * @since JavaFX 2.1 1281 */ 1282 public final <T extends Event> void removeEventHandler( 1283 final EventType<T> eventType, 1284 final EventHandler<? super T> eventHandler) { 1285 checkThread(); 1286 getEventHelper().removeEventHandler(eventType, eventHandler); 1287 } 1288 1289 /** 1290 * Registers an event filter to this task. Registered event filters get 1291 * an event before any associated event handlers. 1292 * 1293 * @param <T> the specific event class of the filter 1294 * @param eventType the type of the events to receive by the filter 1295 * @param eventFilter the filter to register 1296 * @throws NullPointerException if the event type or filter is null 1297 * @since JavaFX 2.1 1298 */ 1299 public final <T extends Event> void addEventFilter( 1300 final EventType<T> eventType, 1301 final EventHandler<? super T> eventFilter) { 1302 checkThread(); 1303 getEventHelper().addEventFilter(eventType, eventFilter); 1304 } 1305 1306 /** 1307 * Unregisters a previously registered event filter from this task. One 1308 * filter might have been registered for different event types, so the 1309 * caller needs to specify the particular event type from which to 1310 * unregister the filter. 1311 * 1312 * @param <T> the specific event class of the filter 1313 * @param eventType the event type from which to unregister 1314 * @param eventFilter the filter to unregister 1315 * @throws NullPointerException if the event type or filter is null 1316 * @since JavaFX 2.1 1317 */ 1318 public final <T extends Event> void removeEventFilter( 1319 final EventType<T> eventType, 1320 final EventHandler<? super T> eventFilter) { 1321 checkThread(); 1322 getEventHelper().removeEventFilter(eventType, eventFilter); 1323 } 1324 1325 /** 1326 * Sets the handler to use for this event type. There can only be one such 1327 * handler specified at a time. This handler is guaranteed to be called 1328 * first. This is used for registering the user-defined onFoo event 1329 * handlers. 1330 * 1331 * @param <T> the specific event class of the handler 1332 * @param eventType the event type to associate with the given eventHandler 1333 * @param eventHandler the handler to register, or null to unregister 1334 * @throws NullPointerException if the event type is null 1335 * @since JavaFX 2.1 1336 */ 1337 protected final <T extends Event> void setEventHandler( 1338 final EventType<T> eventType, 1339 final EventHandler<? super T> eventHandler) { 1340 checkThread(); 1341 getEventHelper().setEventHandler(eventType, eventHandler); 1342 } 1343 1344 /** 1345 * Fires the specified event. Any event filter encountered will 1346 * be notified and can consume the event. If not consumed by the filters, 1347 * the event handlers on this task are notified. If these don't consume the 1348 * event either, then all event handlers are called and can consume the 1349 * event. 1350 * <p> 1351 * This method must be called on the FX user thread. 1352 * 1353 * @param event the event to fire 1354 * @since JavaFX 2.1 1355 */ 1356 public final void fireEvent(Event event) { 1357 checkThread(); 1358 getEventHelper().fireEvent(event); 1359 } 1360 1361 @Override 1362 public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 1363 checkThread(); 1364 return getEventHelper().buildEventDispatchChain(tail); 1365 } 1366 1367 /** 1368 * A struct like class that contains the last workDone update information. 1369 * What we do when updateProgress is called, is we create a new ProgressUpdate 1370 * object and store it. If it was null, then we fire off a new Runnable 1371 * using RunLater, which will eventually read the latest and set it to null 1372 * atomically. If it was not null, then we simply update it. 1373 */ 1374 private static final class ProgressUpdate { 1375 private final double workDone; 1376 private final double totalWork; 1377 1378 private ProgressUpdate(double p, double m) { 1379 this.workDone = p; 1380 this.totalWork = m; 1381 } 1382 } 1383 1384 /** 1385 * TaskCallable actually implements the Callable contract as defined for 1386 * the FutureTask class, and is necessary so as to allow us to intercept 1387 * the call() operation to update state on the Task as appropriate. 1388 * @param <V> 1389 */ 1390 private static final class TaskCallable<V> implements Callable<V> { 1391 /** 1392 * The Task that is going to use this TaskCallable 1393 */ 1394 private Task<V> task; 1395 1396 /** 1397 * Create a TaskCallable. The concurrent and other fields MUST be set 1398 * immediately after creation. 1399 */ 1400 private TaskCallable() { } 1401 1402 /** 1403 * Invoked by the system when it is time to run the client code. This 1404 * implementation is where we modify the state and other properties 1405 * and from which we invoke the events. 1406 * 1407 * @return The result of the Task call method 1408 * @throws Exception any exception which occurred 1409 */ 1410 @Override public V call() throws Exception { 1411 // If the Task is sent to an ExecutorService for execution, then we 1412 // will need to make sure that we transition first to the SCHEDULED 1413 // state before then transitioning to the RUNNING state. If the 1414 // Task was executed by a Service, then it will have already been 1415 // in the SCHEDULED state and setting it again here has no negative 1416 // effect. But we must ensure that SCHEDULED is visited before RUNNING 1417 // in all cases so that developer code can be consistent. 1418 task.started = true; 1419 task.runLater(() -> { 1420 task.setState(State.SCHEDULED); 1421 task.setState(State.RUNNING); 1422 }); 1423 // Go ahead and delegate to the wrapped callable 1424 try { 1425 final V result = task.call(); 1426 if (!task.isCancelled()) { 1427 // If it was not cancelled, then we take the return 1428 // value and set it as the result. 1429 task.runLater(() -> { 1430 // The result must be set first, so that when the 1431 // SUCCEEDED flag is set, the value will be available 1432 // The alternative is not the case, because you 1433 // can assume if the result is set, it has 1434 // succeeded. 1435 task.updateValue(result); 1436 task.setState(State.SUCCEEDED); 1437 }); 1438 return result; 1439 } else { 1440 // Since cancelled Future/FutureTask doesn't return any value, 1441 // the returned value is going to be trashed, so we can jus return null 1442 return null; 1443 } 1444 } catch (final Throwable th) { 1445 // Be sure to set the state after setting the cause of failure 1446 // so that developers handling the state change events have a 1447 // throwable to inspect when they get the FAILED state. Note 1448 // that the other way around is not important -- when a developer 1449 // observes the causeOfFailure is set to a non-null value, even 1450 // though the state has not yet been updated, he can infer that 1451 // it will be FAILED because it can be nothing other than FAILED 1452 // in that circumstance. 1453 task.runLater(() -> { 1454 task._setException(th); 1455 task.setState(State.FAILED); 1456 }); 1457 // Some error occurred during the call (it might be 1458 // an exception (either runtime or checked), or it might 1459 // be an error. In any case, we capture the throwable, 1460 // record it as the causeOfFailure, and then rethrow. However 1461 // since the Callable interface requires that we throw an 1462 // Exception (not Throwable), we have to wrap the exception 1463 // if it is not already one. 1464 if (th instanceof Exception) { 1465 throw (Exception) th; 1466 } else { 1467 throw new Exception(th); 1468 } 1469 } 1470 } 1471 } 1472 }