00001 /* $Id$ */ 00002 00003 /* 00004 * This file is part of OpenTTD. 00005 * 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. 00006 * 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. 00007 * 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/>. 00008 */ 00009 00012 #ifndef YAPF_COSTCACHE_HPP 00013 #define YAPF_COSTCACHE_HPP 00014 00015 #include "../../date_func.h" 00016 00022 template <class Types> 00023 class CYapfSegmentCostCacheNoneT 00024 { 00025 public: 00026 typedef typename Types::Tpf Tpf; 00027 typedef typename Types::NodeList::Titem Node; 00028 00033 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00034 { 00035 return false; 00036 } 00037 00042 FORCEINLINE void PfNodeCacheFlush(Node& n) 00043 { 00044 } 00045 }; 00046 00047 00053 template <class Types> 00054 class CYapfSegmentCostCacheLocalT 00055 { 00056 public: 00057 typedef typename Types::Tpf Tpf; 00058 typedef typename Types::NodeList::Titem Node; 00059 typedef typename Node::Key Key; 00060 typedef typename Node::CachedData CachedData; 00061 typedef typename CachedData::Key CacheKey; 00062 typedef SmallArray<CachedData> LocalCache; 00063 00064 protected: 00065 LocalCache m_local_cache; 00066 00068 FORCEINLINE Tpf& Yapf() 00069 { 00070 return *static_cast<Tpf*>(this); 00071 } 00072 00073 public: 00078 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00079 { 00080 CacheKey key(n.GetKey()); 00081 Yapf().ConnectNodeToCachedData(n, *new (m_local_cache.Append()) CachedData(key)); 00082 return false; 00083 } 00084 00089 FORCEINLINE void PfNodeCacheFlush(Node& n) 00090 { 00091 } 00092 }; 00093 00094 00102 struct CSegmentCostCacheBase 00103 { 00104 static int s_rail_change_counter; 00105 00106 static void NotifyTrackLayoutChange(TileIndex tile, Track track) 00107 { 00108 s_rail_change_counter++; 00109 } 00110 }; 00111 00112 00123 template <class Tsegment> 00124 struct CSegmentCostCacheT 00125 : public CSegmentCostCacheBase 00126 { 00127 static const int C_HASH_BITS = 14; 00128 00129 typedef CHashTableT<Tsegment, C_HASH_BITS> HashTable; 00130 typedef SmallArray<Tsegment> Heap; 00131 typedef typename Tsegment::Key Key; 00132 00133 HashTable m_map; 00134 Heap m_heap; 00135 00136 FORCEINLINE CSegmentCostCacheT() {} 00137 00139 FORCEINLINE void Flush() 00140 { 00141 m_map.Clear(); 00142 m_heap.Clear(); 00143 } 00144 00145 FORCEINLINE Tsegment& Get(Key& key, bool *found) 00146 { 00147 Tsegment *item = m_map.Find(key); 00148 if (item == NULL) { 00149 *found = false; 00150 item = new (m_heap.Append()) Tsegment(key); 00151 m_map.Push(*item); 00152 } else { 00153 *found = true; 00154 } 00155 return *item; 00156 } 00157 }; 00158 00164 template <class Types> 00165 class CYapfSegmentCostCacheGlobalT 00166 : public CYapfSegmentCostCacheLocalT<Types> 00167 { 00168 public: 00169 typedef CYapfSegmentCostCacheLocalT<Types> Tlocal; 00170 typedef typename Types::Tpf Tpf; 00171 typedef typename Types::NodeList::Titem Node; 00172 typedef typename Node::Key Key; 00173 typedef typename Node::CachedData CachedData; 00174 typedef typename CachedData::Key CacheKey; 00175 typedef CSegmentCostCacheT<CachedData> Cache; 00176 00177 protected: 00178 Cache& m_global_cache; 00179 00180 FORCEINLINE CYapfSegmentCostCacheGlobalT() : m_global_cache(stGetGlobalCache()) {}; 00181 00183 FORCEINLINE Tpf& Yapf() 00184 { 00185 return *static_cast<Tpf*>(this); 00186 } 00187 00188 FORCEINLINE static Cache& stGetGlobalCache() 00189 { 00190 static int last_rail_change_counter = 0; 00191 static Date last_date = 0; 00192 static Cache C; 00193 00194 /* some statistics */ 00195 if (last_date != _date) { 00196 last_date = _date; 00197 DEBUG(yapf, 2, "Pf time today: %5d ms", _total_pf_time_us / 1000); 00198 _total_pf_time_us = 0; 00199 } 00200 00201 /* delete the cache sometimes... */ 00202 if (last_rail_change_counter != Cache::s_rail_change_counter) { 00203 last_rail_change_counter = Cache::s_rail_change_counter; 00204 C.Flush(); 00205 } 00206 return C; 00207 } 00208 00209 public: 00214 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00215 { 00216 if (!Yapf().CanUseGlobalCache(n)) { 00217 return Tlocal::PfNodeCacheFetch(n); 00218 } 00219 CacheKey key(n.GetKey()); 00220 bool found; 00221 CachedData& item = m_global_cache.Get(key, &found); 00222 Yapf().ConnectNodeToCachedData(n, item); 00223 return found; 00224 } 00225 00230 FORCEINLINE void PfNodeCacheFlush(Node& n) 00231 { 00232 } 00233 }; 00234 00235 #endif /* YAPF_COSTCACHE_HPP */