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