View Javadoc
1   package org.opentrafficsim.core.perception;
2   
3   import java.util.Collections;
4   import java.util.Map;
5   import java.util.Set;
6   import java.util.WeakHashMap;
7   
8   import org.djunits.value.vdouble.scalar.Duration;
9   import org.djunits.value.vdouble.scalar.Time;
10  
11  import nl.tudelft.simulation.dsol.experiment.Replication;
12  import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit;
13  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
14  
15  /**
16   * History manager with automatic garbage collection by the java garbage collector using weak references to the
17   * {@code Historical}s.
18   * <p>
19   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
20   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
21   * <p>
22   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 18 jan. 2018 <br>
23   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
24   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
25   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
26   */
27  public abstract class HistoryManager
28  {
29  
30      // HACK ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31      // TODO remove this hack and obtain manager from somewhere else, OTSReplication?
32      /** Centrally stored manager. */
33      private static Map<Replication<Time, Duration, SimTimeDoubleUnit>, HistoryManagerDEVS> managers = new WeakHashMap<>();
34  
35      /**
36       * Get central manager.
37       * @param simulator DEVSSimulatorInterface.TimeDoubleUnit; simulator
38       * @return HistoryManagerDEVS; central manager
39       */
40      public static HistoryManagerDEVS get(final DEVSSimulatorInterface.TimeDoubleUnit simulator)
41      {
42          HistoryManagerDEVS manager = managers.get(simulator.getReplication());
43          if (manager == null)
44          {
45              manager = new HistoryManagerDEVS(simulator, Duration.createSI(0.0), Duration.createSI(10.0));
46              managers.put(simulator.getReplication(), manager);
47          }
48          return manager;
49      }
50  
51      /**
52       * Set central manager.
53       * @param manager HistoryManagerDEVS; manager
54       * @param simulator DEVSSimulatorInterface.TimeDoubleUnit; simulator
55       */
56      public static void set(final HistoryManagerDEVS manager, final DEVSSimulatorInterface.TimeDoubleUnit simulator)
57      {
58          managers.put(simulator.getReplication(), manager);
59      }
60  
61      /**
62       * Clear central manager. If this is not done in batch simulations, this forms a memory leak.
63       * @param simulator DEVSSimulatorInterface.TimeDoubleUnit; simulator
64       */
65      public static void clear(final DEVSSimulatorInterface.TimeDoubleUnit simulator)
66      {
67          managers.remove(simulator.getReplication());
68      }
69      // END OF HACK /////////////////////////////////////////////////////////////////////////////////////////////////////////////
70  
71      /** Set of all {@code Historical}s. */
72      // There's no WeakSet, but this is effectively the same. Iterating over this is safe, only alive objects are returned.
73      private final Set<HistoricalElement> historicals = Collections.newSetFromMap(new WeakHashMap<HistoricalElement, Boolean>());
74  
75      /**
76       * Registers a historical.
77       * @param historical Historical; historical to register.
78       */
79      public void registerHistorical(final HistoricalElement historical)
80      {
81          if (historical != null)
82          {
83              this.historicals.add(historical);
84          }
85      }
86  
87      /**
88       * Returns the historicals.
89       * @return the historicals
90       */
91      protected final Set<HistoricalElement> getHistoricals()
92      {
93          return this.historicals;
94      }
95  
96      /**
97       * Returns the current simulation time. This is used by historicals to time-stamp state changes.
98       * @return Time; current simulation time.
99       */
100     abstract Time now();
101 
102     /**
103      * Historical view for the history manager.
104      * <p>
105      * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
106      * <br>
107      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
108      * <p>
109      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 feb. 2018 <br>
110      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
111      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
112      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
113      */
114     public interface HistoricalElement
115     {
116         /**
117          * Removes events that are no longer needed to guarantee the history time. This is invoked by the history manager.
118          * @param history Duration; history time to keep
119          */
120         void cleanUpHistory(Duration history);
121     }
122 
123     /**
124      * Method that clears the entire memory at simulation end.
125      */
126     protected final void endOfSimulation()
127     {
128         for (HistoricalElement historical : this.historicals)
129         {
130             historical.cleanUpHistory(Duration.ZERO);
131         }
132         this.historicals.clear();
133     }
134 
135 }