00001 /* $Id: yapf_costcache.hpp 15718 2009-03-15 00:32:18Z rubidium $ */ 00002 00005 #ifndef YAPF_COSTCACHE_HPP 00006 #define YAPF_COSTCACHE_HPP 00007 00008 #include "../date_func.h" 00009 00014 template <class Types> 00015 class CYapfSegmentCostCacheNoneT 00016 { 00017 public: 00018 typedef typename Types::Tpf Tpf; 00019 typedef typename Types::NodeList::Titem Node; 00020 00023 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00024 { 00025 return false; 00026 } 00027 00030 FORCEINLINE void PfNodeCacheFlush(Node& n) 00031 { 00032 } 00033 }; 00034 00035 00040 template <class Types> 00041 class CYapfSegmentCostCacheLocalT 00042 { 00043 public: 00044 typedef typename Types::Tpf Tpf; 00045 typedef typename Types::NodeList::Titem Node; 00046 typedef typename Node::Key Key; 00047 typedef typename Node::CachedData CachedData; 00048 typedef typename CachedData::Key CacheKey; 00049 typedef CArrayT<CachedData> LocalCache; 00050 00051 protected: 00052 LocalCache m_local_cache; 00053 00055 FORCEINLINE Tpf& Yapf() 00056 { 00057 return *static_cast<Tpf*>(this); 00058 } 00059 00060 public: 00063 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00064 { 00065 CacheKey key(n.GetKey()); 00066 Yapf().ConnectNodeToCachedData(n, *new (&m_local_cache.AddNC()) CachedData(key)); 00067 return false; 00068 } 00069 00072 FORCEINLINE void PfNodeCacheFlush(Node& n) 00073 { 00074 } 00075 }; 00076 00077 00083 struct CSegmentCostCacheBase 00084 { 00085 static int s_rail_change_counter; 00086 00087 static void NotifyTrackLayoutChange(TileIndex tile, Track track) 00088 { 00089 s_rail_change_counter++; 00090 } 00091 }; 00092 00093 00102 template <class Tsegment> 00103 struct CSegmentCostCacheT 00104 : public CSegmentCostCacheBase 00105 { 00106 enum {c_hash_bits = 14}; 00107 00108 typedef CHashTableT<Tsegment, c_hash_bits> HashTable; 00109 typedef CArrayT<Tsegment> Heap; 00110 typedef typename Tsegment::Key Key; 00111 00112 HashTable m_map; 00113 Heap m_heap; 00114 00115 FORCEINLINE CSegmentCostCacheT() {} 00116 00118 FORCEINLINE void Flush() 00119 { 00120 m_map.Clear(); 00121 m_heap.Clear(); 00122 } 00123 00124 FORCEINLINE Tsegment& Get(Key& key, bool *found) 00125 { 00126 Tsegment *item = m_map.Find(key); 00127 if (item == NULL) { 00128 *found = false; 00129 item = new (&m_heap.AddNC()) Tsegment(key); 00130 m_map.Push(*item); 00131 } else { 00132 *found = true; 00133 } 00134 return *item; 00135 } 00136 }; 00137 00142 template <class Types> 00143 class CYapfSegmentCostCacheGlobalT 00144 : public CYapfSegmentCostCacheLocalT<Types> 00145 { 00146 public: 00147 typedef CYapfSegmentCostCacheLocalT<Types> Tlocal; 00148 typedef typename Types::Tpf Tpf; 00149 typedef typename Types::NodeList::Titem Node; 00150 typedef typename Node::Key Key; 00151 typedef typename Node::CachedData CachedData; 00152 typedef typename CachedData::Key CacheKey; 00153 typedef CSegmentCostCacheT<CachedData> Cache; 00154 00155 protected: 00156 Cache& m_global_cache; 00157 00158 FORCEINLINE CYapfSegmentCostCacheGlobalT() : m_global_cache(stGetGlobalCache()) {}; 00159 00161 FORCEINLINE Tpf& Yapf() 00162 { 00163 return *static_cast<Tpf*>(this); 00164 } 00165 00166 FORCEINLINE static Cache& stGetGlobalCache() 00167 { 00168 static int last_rail_change_counter = 0; 00169 static Date last_date = 0; 00170 static Cache C; 00171 00172 /* some statistics */ 00173 if (last_date != _date) { 00174 last_date = _date; 00175 DEBUG(yapf, 2, "Pf time today: %5d ms", _total_pf_time_us / 1000); 00176 _total_pf_time_us = 0; 00177 } 00178 00179 /* delete the cache sometimes... */ 00180 if (last_rail_change_counter != Cache::s_rail_change_counter) { 00181 last_rail_change_counter = Cache::s_rail_change_counter; 00182 C.Flush(); 00183 } 00184 return C; 00185 } 00186 00187 public: 00190 FORCEINLINE bool PfNodeCacheFetch(Node& n) 00191 { 00192 if (!Yapf().CanUseGlobalCache(n)) { 00193 return Tlocal::PfNodeCacheFetch(n); 00194 } 00195 CacheKey key(n.GetKey()); 00196 bool found; 00197 CachedData& item = m_global_cache.Get(key, &found); 00198 Yapf().ConnectNodeToCachedData(n, item); 00199 return found; 00200 } 00201 00204 FORCEINLINE void PfNodeCacheFlush(Node& n) 00205 { 00206 } 00207 }; 00208 00209 #endif /* YAPF_COSTCACHE_HPP */