Add: INR currency (#8136)
[openttd-github.git] / src / pathfinder / yapf / yapf_costcache.hpp
blobc56c47b5f2cdd7e36692ebec38fbcb4058621dde
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
8 /** @file yapf_costcache.hpp Caching of segment costs. */
10 #ifndef YAPF_COSTCACHE_HPP
11 #define YAPF_COSTCACHE_HPP
13 #include "../../date_func.h"
15 /**
16 * CYapfSegmentCostCacheNoneT - the formal only yapf cost cache provider that implements
17 * PfNodeCacheFetch() and PfNodeCacheFlush() callbacks. Used when nodes don't have CachedData
18 * defined (they don't count with any segment cost caching).
20 template <class Types>
21 class CYapfSegmentCostCacheNoneT
23 public:
24 typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
25 typedef typename Types::NodeList::Titem Node; ///< this will be our node type
27 /**
28 * Called by YAPF to attach cached or local segment cost data to the given node.
29 * @return true if globally cached data were used or false if local data was used
31 inline bool PfNodeCacheFetch(Node &n)
33 return false;
36 /**
37 * Called by YAPF to flush the cached segment cost data back into cache storage.
38 * Current cache implementation doesn't use that.
40 inline void PfNodeCacheFlush(Node &n)
46 /**
47 * CYapfSegmentCostCacheLocalT - the yapf cost cache provider that implements fake segment
48 * cost caching functionality for yapf. Used when node needs caching, but you don't want to
49 * cache the segment costs.
51 template <class Types>
52 class CYapfSegmentCostCacheLocalT
54 public:
55 typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
56 typedef typename Types::NodeList::Titem Node; ///< this will be our node type
57 typedef typename Node::Key Key; ///< key to hash tables
58 typedef typename Node::CachedData CachedData;
59 typedef typename CachedData::Key CacheKey;
60 typedef SmallArray<CachedData> LocalCache;
62 protected:
63 LocalCache m_local_cache;
65 /** to access inherited path finder */
66 inline Tpf& Yapf()
68 return *static_cast<Tpf *>(this);
71 public:
72 /**
73 * Called by YAPF to attach cached or local segment cost data to the given node.
74 * @return true if globally cached data were used or false if local data was used
76 inline bool PfNodeCacheFetch(Node &n)
78 CacheKey key(n.GetKey());
79 Yapf().ConnectNodeToCachedData(n, *new (m_local_cache.Append()) CachedData(key));
80 return false;
83 /**
84 * Called by YAPF to flush the cached segment cost data back into cache storage.
85 * Current cache implementation doesn't use that.
87 inline void PfNodeCacheFlush(Node &n)
93 /**
94 * Base class for segment cost cache providers. Contains global counter
95 * of track layout changes and static notification function called whenever
96 * the track layout changes. It is implemented as base class because it needs
97 * to be shared between all rail YAPF types (one shared counter, one notification
98 * function.
100 struct CSegmentCostCacheBase
102 static int s_rail_change_counter;
104 static void NotifyTrackLayoutChange(TileIndex tile, Track track)
106 s_rail_change_counter++;
112 * CSegmentCostCacheT - template class providing hash-map and storage (heap)
113 * of Tsegment structures. Each rail node contains pointer to the segment
114 * that contains cached (or non-cached) segment cost information. Nodes can
115 * differ by key type, but they use the same segment type. Segment key should
116 * be always the same (TileIndex + DiagDirection) that represent the beginning
117 * of the segment (origin tile and exit-dir from this tile).
118 * Different CYapfCachedCostT types can share the same type of CSegmentCostCacheT.
119 * Look at CYapfRailSegment (yapf_node_rail.hpp) for the segment example
121 template <class Tsegment>
122 struct CSegmentCostCacheT : public CSegmentCostCacheBase {
123 static const int C_HASH_BITS = 14;
125 typedef CHashTableT<Tsegment, C_HASH_BITS> HashTable;
126 typedef SmallArray<Tsegment> Heap;
127 typedef typename Tsegment::Key Key; ///< key to hash table
129 HashTable m_map;
130 Heap m_heap;
132 inline CSegmentCostCacheT() {}
134 /** flush (clear) the cache */
135 inline void Flush()
137 m_map.Clear();
138 m_heap.Clear();
141 inline Tsegment& Get(Key &key, bool *found)
143 Tsegment *item = m_map.Find(key);
144 if (item == nullptr) {
145 *found = false;
146 item = new (m_heap.Append()) Tsegment(key);
147 m_map.Push(*item);
148 } else {
149 *found = true;
151 return *item;
156 * CYapfSegmentCostCacheGlobalT - the yapf cost cache provider that adds the segment cost
157 * caching functionality to yapf. Using this class as base of your will provide the global
158 * segment cost caching services for your Nodes.
160 template <class Types>
161 class CYapfSegmentCostCacheGlobalT : public CYapfSegmentCostCacheLocalT<Types> {
162 public:
163 typedef CYapfSegmentCostCacheLocalT<Types> Tlocal;
164 typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
165 typedef typename Types::NodeList::Titem Node; ///< this will be our node type
166 typedef typename Node::Key Key; ///< key to hash tables
167 typedef typename Node::CachedData CachedData;
168 typedef typename CachedData::Key CacheKey;
169 typedef CSegmentCostCacheT<CachedData> Cache;
171 protected:
172 Cache &m_global_cache;
174 inline CYapfSegmentCostCacheGlobalT() : m_global_cache(stGetGlobalCache()) {};
176 /** to access inherited path finder */
177 inline Tpf& Yapf()
179 return *static_cast<Tpf *>(this);
182 inline static Cache& stGetGlobalCache()
184 static int last_rail_change_counter = 0;
185 static Date last_date = 0;
186 static Cache C;
188 /* some statistics */
189 if (last_date != _date) {
190 last_date = _date;
191 DEBUG(yapf, 2, "Pf time today: %5d ms", _total_pf_time_us / 1000);
192 _total_pf_time_us = 0;
195 /* delete the cache sometimes... */
196 if (last_rail_change_counter != Cache::s_rail_change_counter) {
197 last_rail_change_counter = Cache::s_rail_change_counter;
198 C.Flush();
200 return C;
203 public:
205 * Called by YAPF to attach cached or local segment cost data to the given node.
206 * @return true if globally cached data were used or false if local data was used
208 inline bool PfNodeCacheFetch(Node &n)
210 if (!Yapf().CanUseGlobalCache(n)) {
211 return Tlocal::PfNodeCacheFetch(n);
213 CacheKey key(n.GetKey());
214 bool found;
215 CachedData &item = m_global_cache.Get(key, &found);
216 Yapf().ConnectNodeToCachedData(n, item);
217 return found;
221 * Called by YAPF to flush the cached segment cost data back into cache storage.
222 * Current cache implementation doesn't use that.
224 inline void PfNodeCacheFlush(Node &n)
229 #endif /* YAPF_COSTCACHE_HPP */