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 }