View Javadoc
1   package org.opentrafficsim.core.egtf;
2   
3   /**
4    * Listener that allows another thread to monitor, report on, and wait for the filtering result.
5    * <p>
6    * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
7    * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
8    * <p>
9    * @version $Revision$, $LastChangedDate$, by $Author$, initial version 24 okt. 2018 <br>
10   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
11   */
12  public class EgtfParallelListener implements EgtfListener
13  {
14  
15      /** Filter results after the EGTF is done. */
16      private Filter filter;
17  
18      /** Wait lock. */
19      private Object lock = new Object();
20  
21      /** Progress at the last event. */
22      private double progress = 0.0;
23  
24      /** Whether the user interrupted the EGTF. */
25      private boolean interrupted = false;
26  
27      /**
28       * Package-private constructor.
29       */
30      EgtfParallelListener()
31      {
32          //
33      }
34  
35      /**
36       * Waits until progress has been reached, or timeout was exceeded.
37       * @param untilProgress double; progress to wait until
38       * @param timeout long; time out in milliseconds
39       * @return double; value equal to or above untilProgress, or lower if the timeout was exceeded
40       * @throws InterruptedException when the calling thread is interrupted
41       */
42      public double wait(final double untilProgress, final long timeout) throws InterruptedException
43      {
44          long t1 = System.currentTimeMillis() + timeout;
45          long tOut = timeout;
46          double uProgress = Math.min(1.0, untilProgress);
47          while (this.progress < uProgress && tOut > 0)
48          {
49              synchronized (this.lock)
50              {
51                  this.lock.wait(tOut);
52              }
53              tOut = t1 - System.currentTimeMillis();
54          }
55          return this.progress;
56      }
57  
58      /**
59       * Set the filter results, this is done by the EGTF.
60       * @param filter Filter; filter results
61       */
62      public void setFilter(final Filter filter)
63      {
64          this.filter = filter;
65          this.progress = 1.0;
66          synchronized (this.lock)
67          {
68              this.lock.notifyAll();
69          }
70      }
71  
72      /**
73       * Get the filter results after the EGTF is done.
74       * @return Filter; filter results
75       */
76      public Filter getFilter()
77      {
78          if (this.filter == null)
79          {
80              throw new IllegalStateException("Trying to obtain the filter results before filtering is done.");
81          }
82          return this.filter;
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      public void notifyProgress(final EgtfEvent event)
88      {
89          if (this.interrupted)
90          {
91              event.interrupt();
92              this.progress = 1.0;
93          }
94          else
95          {
96              // set the current progress, but do not allow a value of 1.0 until the filter result is actually set
97              this.progress = Math.min(event.getProgress(), 1.0 - 1e-9);
98          }
99          synchronized (this.lock)
100         {
101             this.lock.notifyAll();
102         }
103     }
104 
105     /**
106      * Interrupts the EGTF.
107      */
108     public void interrupt()
109     {
110         this.interrupted = true;
111     }
112 
113     /** {@inheritDoc} */
114     @Override
115     public String toString()
116     {
117         return "EgtfParallelListener [filter=" + this.filter + ", progress=" + this.progress + "]";
118     }
119 
120 }