View Javadoc
1   package org.opentrafficsim.draw.graphs;
2   
3   import java.util.concurrent.BlockingQueue;
4   import java.util.concurrent.LinkedBlockingQueue;
5   import java.util.concurrent.TimeUnit;
6   
7   import org.opentrafficsim.base.logger.Logger;
8   
9   /**
10   * The GraphUpdater can be used to repeatedly offer a value that is automatically processed in order of offering in a parallel
11   * Thread.
12   * <p>
13   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
15   * </p>
16   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
17   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
18   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
19   * @param <T> type of value in queue
20   */
21  public class GraphUpdater<T>
22  {
23  
24      /** Queue of update times for executing Thread. */
25      private final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
26  
27      /** Default updater. */
28      private final Updater<T> updater;
29  
30      /**
31       * Constructs and starts a thread that performs each given task from a queue.
32       * @param workerName name for the working thread
33       * @param invokingThread invoking thread, the worker will stop when this thread is interrupted
34       * @param updater updater to perform with the queued value
35       */
36      public GraphUpdater(final String workerName, final Thread invokingThread, final Updater<T> updater)
37      {
38          this.updater = updater;
39          new Thread(new Runnable()
40          {
41              @Override
42              public void run()
43              {
44                  while (!invokingThread.isInterrupted())
45                  {
46                      try
47                      {
48                          Runnable runnable = GraphUpdater.this.queue.poll(5, TimeUnit.SECONDS);
49                          if (runnable != null)
50                          {
51                              runnable.run();
52                          }
53                      }
54                      catch (InterruptedException exception)
55                      {
56                          Logger.ots().error(exception, "Worker {} thread stopped.", workerName);
57                          break;
58                      }
59                  }
60              }
61          }, workerName).start();
62      }
63  
64      /**
65       * Offer a next value to the queue for the default updater.
66       * @param t next value to offer to the queue
67       */
68      public final void offer(final T t)
69      {
70          this.queue.offer(() -> this.updater.update(t));
71      }
72  
73      /**
74       * Add specific runnable to the queue.
75       * @param runnable specific runnable for the queue
76       */
77      public final void offer(final Runnable runnable)
78      {
79          this.queue.offer(runnable);
80      }
81  
82      /**
83       * Functional interface for updates to perform.
84       * <p>
85       * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
86       * <br>
87       * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
88       * </p>
89       * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
90       * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
91       * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
92       * @param <T> type of value in queue
93       */
94      @FunctionalInterface
95      interface Updater<T>
96      {
97          /**
98           * Perform an update.
99           * @param t value to update by
100          */
101         void update(T t);
102     }
103 
104     @Override
105     public String toString()
106     {
107         return "GraphUpdater [queue=" + this.queue + "]";
108     }
109 
110 }