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/>.
8 /** @file yapf_costcache.hpp Caching of segment costs. */
10 #ifndef YAPF_COSTCACHE_HPP
11 #define YAPF_COSTCACHE_HPP
13 #include "../../misc/hashtable.hpp"
14 #include "../../tile_type.h"
15 #include "../../track_type.h"
18 * CYapfSegmentCostCacheNoneT - the formal only yapf cost cache provider that implements
19 * PfNodeCacheFetch(). Used when nodes don't have CachedData
20 * defined (they don't count with any segment cost caching).
22 template <class Types
>
23 class CYapfSegmentCostCacheNoneT
26 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
27 typedef typename
Types::NodeList::Item Node
; ///< this will be our node type
30 * Called by YAPF to attach cached or local segment cost data to the given node.
31 * @return true if globally cached data were used or false if local data was used
33 inline bool PfNodeCacheFetch(Node
&)
40 * Base class for segment cost cache providers. Contains global counter
41 * of track layout changes and static notification function called whenever
42 * the track layout changes. It is implemented as base class because it needs
43 * to be shared between all rail YAPF types (one shared counter, one notification
46 struct CSegmentCostCacheBase
48 static int s_rail_change_counter
;
50 static void NotifyTrackLayoutChange(TileIndex
, Track
)
52 s_rail_change_counter
++;
58 * CSegmentCostCacheT - template class providing hash-map and storage (heap)
59 * of Tsegment structures. Each rail node contains pointer to the segment
60 * that contains cached (or non-cached) segment cost information. Nodes can
61 * differ by key type, but they use the same segment type. Segment key should
62 * be always the same (TileIndex + DiagDirection) that represent the beginning
63 * of the segment (origin tile and exit-dir from this tile).
64 * Different CYapfCachedCostT types can share the same type of CSegmentCostCacheT.
65 * Look at CYapfRailSegment (yapf_node_rail.hpp) for the segment example
67 template <class Tsegment
>
68 struct CSegmentCostCacheT
: public CSegmentCostCacheBase
{
69 static constexpr int HASH_BITS
= 14;
71 using Key
= typename
Tsegment::Key
; ///< key to hash table
73 HashTable
<Tsegment
, HASH_BITS
> map
;
74 std::deque
<Tsegment
> heap
;
76 inline CSegmentCostCacheT() {}
78 /** flush (clear) the cache */
85 inline Tsegment
&Get(Key
&key
, bool *found
)
87 Tsegment
*item
= this->map
.Find(key
);
88 if (item
== nullptr) {
90 item
= &this->heap
.emplace_back(key
);
91 this->map
.Push(*item
);
100 * CYapfSegmentCostCacheGlobalT - the yapf cost cache provider that adds the segment cost
101 * caching functionality to yapf. Using this class as base of your will provide the global
102 * segment cost caching services for your Nodes.
104 template <class Types
>
105 class CYapfSegmentCostCacheGlobalT
{
107 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
108 typedef typename
Types::NodeList::Item Node
; ///< this will be our node type
109 typedef typename
Node::Key Key
; ///< key to hash tables
110 typedef typename
Node::CachedData CachedData
;
111 typedef typename
CachedData::Key CacheKey
;
112 typedef CSegmentCostCacheT
<CachedData
> Cache
;
113 using LocalCache
= std::deque
<CachedData
>;
117 LocalCache local_cache
;
119 inline CYapfSegmentCostCacheGlobalT() : global_cache(stGetGlobalCache()) {};
121 /** to access inherited path finder */
124 return *static_cast<Tpf
*>(this);
127 inline static Cache
&stGetGlobalCache()
129 static int last_rail_change_counter
= 0;
132 /* delete the cache sometimes... */
133 if (last_rail_change_counter
!= Cache::s_rail_change_counter
) {
134 last_rail_change_counter
= Cache::s_rail_change_counter
;
142 * Called by YAPF to attach cached or local segment cost data to the given node.
143 * @return true if globally cached data were used or false if local data was used
145 inline bool PfNodeCacheFetch(Node
&n
)
147 CacheKey
key(n
.GetKey());
149 if (!Yapf().CanUseGlobalCache(n
)) {
150 Yapf().ConnectNodeToCachedData(n
, this->local_cache
.emplace_back(key
));
155 CachedData
&item
= this->global_cache
.Get(key
, &found
);
156 Yapf().ConnectNodeToCachedData(n
, item
);
161 #endif /* YAPF_COSTCACHE_HPP */