00001 /* $Id: yapf_costcache.hpp 18826 2010-01-16 14:22:19Z frosch $ */ 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 00021 template <class Types> 00022 class CYapfSegmentCostCacheNoneT 00023 { 00024 public: 00025 typedef typename Types::Tpf Tpf; 00026 typedef typename Types::NodeList::Titem Node; 00027 00030 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00031 { 00032 return false; 00033 } 00034 00037 FORCEINLINE void PfNodeCacheFlush(Node& n) 00038 { 00039 } 00040 }; 00041 00042 00047 template <class Types> 00048 class CYapfSegmentCostCacheLocalT 00049 { 00050 public: 00051 typedef typename Types::Tpf Tpf; 00052 typedef typename Types::NodeList::Titem Node; 00053 typedef typename Node::Key Key; 00054 typedef typename Node::CachedData CachedData; 00055 typedef typename CachedData::Key CacheKey; 00056 typedef SmallArray<CachedData> LocalCache; 00057 00058 protected: 00059 LocalCache m_local_cache; 00060 00062 FORCEINLINE Tpf& Yapf() 00063 { 00064 return *static_cast<Tpf*>(this); 00065 } 00066 00067 public: 00070 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00071 { 00072 CacheKey key(n.GetKey()); 00073 Yapf().ConnectNodeToCachedData(n, *new (m_local_cache.Append()) CachedData(key)); 00074 return false; 00075 } 00076 00079 FORCEINLINE void PfNodeCacheFlush(Node& n) 00080 { 00081 } 00082 }; 00083 00084 00090 struct CSegmentCostCacheBase 00091 { 00092 static int s_rail_change_counter; 00093 00094 static void NotifyTrackLayoutChange(TileIndex tile, Track track) 00095 { 00096 s_rail_change_counter++; 00097 } 00098 }; 00099 00100 00109 template <class Tsegment> 00110 struct CSegmentCostCacheT 00111 : public CSegmentCostCacheBase 00112 { 00113 enum {c_hash_bits = 14}; 00114 00115 typedef CHashTableT<Tsegment, c_hash_bits> HashTable; 00116 typedef SmallArray<Tsegment> Heap; 00117 typedef typename Tsegment::Key Key; 00118 00119 HashTable m_map; 00120 Heap m_heap; 00121 00122 FORCEINLINE CSegmentCostCacheT() {} 00123 00125 FORCEINLINE void Flush() 00126 { 00127 m_map.Clear(); 00128 m_heap.Clear(); 00129 } 00130 00131 FORCEINLINE Tsegment& Get(Key& key, bool *found) 00132 { 00133 Tsegment *item = m_map.Find(key); 00134 if (item == NULL) { 00135 *found = false; 00136 item = new (m_heap.Append()) Tsegment(key); 00137 m_map.Push(*item); 00138 } else { 00139 *found = true; 00140 } 00141 return *item; 00142 } 00143 }; 00144 00149 template <class Types> 00150 class CYapfSegmentCostCacheGlobalT 00151 : public CYapfSegmentCostCacheLocalT<Types> 00152 { 00153 public: 00154 typedef CYapfSegmentCostCacheLocalT<Types> Tlocal; 00155 typedef typename Types::Tpf Tpf; 00156 typedef typename Types::NodeList::Titem Node; 00157 typedef typename Node::Key Key; 00158 typedef typename Node::CachedData CachedData; 00159 typedef typename CachedData::Key CacheKey; 00160 typedef CSegmentCostCacheT<CachedData> Cache; 00161 00162 protected: 00163 Cache& m_global_cache; 00164 00165 FORCEINLINE CYapfSegmentCostCacheGlobalT() : m_global_cache(stGetGlobalCache()) {}; 00166 00168 FORCEINLINE Tpf& Yapf() 00169 { 00170 return *static_cast<Tpf*>(this); 00171 } 00172 00173 FORCEINLINE static Cache& stGetGlobalCache() 00174 { 00175 static int last_rail_change_counter = 0; 00176 static Date last_date = 0; 00177 static Cache C; 00178 00179 /* some statistics */ 00180 if (last_date != _date) { 00181 last_date = _date; 00182 DEBUG(yapf, 2, "Pf time today: %5d ms", _total_pf_time_us / 1000); 00183 _total_pf_time_us = 0; 00184 } 00185 00186 /* delete the cache sometimes... */ 00187 if (last_rail_change_counter != Cache::s_rail_change_counter) { 00188 last_rail_change_counter = Cache::s_rail_change_counter; 00189 C.Flush(); 00190 } 00191 return C; 00192 } 00193 00194 public: 00197 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00198 { 00199 if (!Yapf().CanUseGlobalCache(n)) { 00200 return Tlocal::PfNodeCacheFetch(n); 00201 } 00202 CacheKey key(n.GetKey()); 00203 bool found; 00204 CachedData& item = m_global_cache.Get(key, &found); 00205 Yapf().ConnectNodeToCachedData(n, item); 00206 return found; 00207 } 00208 00211 FORCEINLINE void PfNodeCacheFlush(Node& n) 00212 { 00213 } 00214 }; 00215 00216 #endif /* YAPF_COSTCACHE_HPP */