yapf/yapf_costcache.hpp
changeset 3900 2c84ed52709d
child 3914 6bdd22b93698
equal deleted inserted replaced
3899:5ba7f20a14ca 3900:2c84ed52709d
       
     1 /* $Id$ */
       
     2 #ifndef  YAPF_COSTCACHE_HPP
       
     3 #define  YAPF_COSTCACHE_HPP
       
     4 
       
     5 
       
     6 /** CYapfSegmentCostCacheNoneT - the formal only yapf cost cache provider that implements
       
     7 PfNodeCacheFetch() and PfNodeCacheFlush() callbacks. Used when nodes don't have CachedData
       
     8 defined (they don't count with any segment cost caching).
       
     9 */
       
    10 template <class Types>
       
    11 class CYapfSegmentCostCacheNoneT
       
    12 {
       
    13 public:
       
    14 	typedef typename Types::Tpf Tpf;
       
    15 	typedef typename Types::NodeList::Titem Node; ///< this will be our node type
       
    16 
       
    17 	FORCEINLINE bool PfNodeCacheFetch(Node& n)
       
    18 	{
       
    19 		return false;
       
    20 	};
       
    21 
       
    22 	FORCEINLINE void PfNodeCacheFlush(Node& n)
       
    23 	{
       
    24 	};
       
    25 };
       
    26 
       
    27 
       
    28 /** CYapfSegmentCostCacheLocalT - the yapf cost cache provider that implements fake segment
       
    29 cost caching functionality for yapf. Used when node needs caching, but you don't want to
       
    30 cache the segment costs.
       
    31 */
       
    32 template <class Types>
       
    33 class CYapfSegmentCostCacheLocalT
       
    34 {
       
    35 public:
       
    36 	typedef typename Types::Tpf Tpf;
       
    37 	typedef typename Types::NodeList::Titem Node; ///< this will be our node type
       
    38 	typedef typename Node::Key Key;    ///< key to hash tables
       
    39 	typedef typename Node::CachedData CachedData;
       
    40 	typedef typename CachedData::Key CacheKey;
       
    41 	typedef CArrayT<CachedData> LocalCache;
       
    42 
       
    43 protected:
       
    44 	LocalCache      m_local_cache;
       
    45 
       
    46 	FORCEINLINE Tpf& Yapf() {return *static_cast<Tpf*>(this);}
       
    47 
       
    48 public:
       
    49 	FORCEINLINE bool PfNodeCacheFetch(Node& n)
       
    50 	{
       
    51 		CacheKey key(n.GetKey());
       
    52 		Yapf().ConnectNodeToCachedData(n, *new (&m_local_cache.AddNC()) CachedData(key));
       
    53 		return false;
       
    54 	};
       
    55 
       
    56 	FORCEINLINE void PfNodeCacheFlush(Node& n)
       
    57 	{
       
    58 	};
       
    59 };
       
    60 
       
    61 
       
    62 
       
    63 struct CSegmentCostCacheBase
       
    64 {
       
    65 	static int   s_rail_change_counter;
       
    66 
       
    67 	static void NotifyTrackLayoutChange(TileIndex tile, Track track) {s_rail_change_counter++;}
       
    68 };
       
    69 
       
    70 
       
    71 /** CSegmentCostCacheT - template class providing hash-map and storage (heap)
       
    72     of Tsegment structures. Each rail node contains pointer to the segment
       
    73     that contains cached (or non-cached) segment cost information. Nodes can
       
    74     differ by key type, but they use the same segment type. Segment key should
       
    75     be always the same (TileIndex + DiagDirection) that represent the beginning
       
    76     of the segment (origin tile and exit-dir from this tile).
       
    77     Different CYapfCachedCostT types can share the same type of CSegmentCostCacheT.
       
    78     Look at CYapfRailSegment (yapf_node_rail.hpp) for the segment example */
       
    79 
       
    80 template <class Tsegment>
       
    81 struct CSegmentCostCacheT
       
    82 	: public CSegmentCostCacheBase
       
    83 {
       
    84 	enum {c_hash_bits = 14};
       
    85 
       
    86 	typedef CHashTableT<Tsegment, c_hash_bits> HashTable;
       
    87 	typedef CArrayT<Tsegment> Heap;
       
    88 	typedef typename Tsegment::Key Key;    ///< key to hash table
       
    89 
       
    90 	HashTable    m_map;
       
    91 	Heap         m_heap;
       
    92 
       
    93 	FORCEINLINE CSegmentCostCacheT() {}
       
    94 
       
    95 	FORCEINLINE Tsegment& Get(Key& key, bool *found)
       
    96 	{
       
    97 		Tsegment* item = &m_map.Find(key);
       
    98 		if (item == NULL) {
       
    99 			*found = false;
       
   100 			item = new (&m_heap.AddNC()) Tsegment(key);
       
   101 			m_map.Push(*item);
       
   102 		} else {
       
   103 			*found = true;
       
   104 		}
       
   105 		return *item;
       
   106 	}
       
   107 };
       
   108 
       
   109 /** CYapfSegmentCostCacheGlobalT - the yapf cost cache provider that adds the segment cost
       
   110     caching functionality to yapf. Using this class as base of your will provide the global
       
   111 		segment cost caching services for your Nodes.
       
   112 */
       
   113 template <class Types>
       
   114 class CYapfSegmentCostCacheGlobalT
       
   115 	: public CYapfSegmentCostCacheLocalT<Types>
       
   116 {
       
   117 public:
       
   118 	typedef CYapfSegmentCostCacheLocalT<Types> Tlocal;
       
   119 	typedef typename Types::Tpf Tpf;
       
   120 	typedef typename Types::NodeList::Titem Node; ///< this will be our node type
       
   121 	typedef typename Node::Key Key;    ///< key to hash tables
       
   122 	typedef typename Node::CachedData CachedData;
       
   123 	typedef typename CachedData::Key CacheKey;
       
   124 	typedef CSegmentCostCacheT<CachedData> Cache;
       
   125 
       
   126 protected:
       
   127 	Cache&      m_global_cache;
       
   128 
       
   129 	FORCEINLINE CYapfSegmentCostCacheGlobalT() : m_global_cache(stGetGlobalCache()) {};
       
   130 
       
   131 	FORCEINLINE Tpf& Yapf() {return *static_cast<Tpf*>(this);}
       
   132 
       
   133 	FORCEINLINE static Cache*& stGlobalCachePtr() {static Cache* pC = NULL; return pC;}
       
   134 
       
   135 	FORCEINLINE static Cache& stGetGlobalCache()
       
   136 	{
       
   137 		static int last_rail_change_counter = 0;
       
   138 		static uint32 last_day = 0;
       
   139 
       
   140 		// some statistics
       
   141 		if (last_day != _date) {
       
   142 			last_day = _date;
       
   143 			DEBUG(yapf, 1)("pf time today:%5d ms\n", _total_pf_time_us / 1000);
       
   144 			_total_pf_time_us = 0;
       
   145 		}
       
   146 
       
   147 		Cache*& pC = stGlobalCachePtr();
       
   148 
       
   149 		// delete the cache sometimes...
       
   150 		if (pC != NULL && last_rail_change_counter != Cache::s_rail_change_counter) {
       
   151 			last_rail_change_counter = Cache::s_rail_change_counter;
       
   152 			delete pC;
       
   153 			pC = NULL;
       
   154 		}
       
   155 
       
   156 		if (pC == NULL)
       
   157 			pC = new Cache();
       
   158 		return *pC;
       
   159 	}
       
   160 
       
   161 public:
       
   162 	FORCEINLINE bool PfNodeCacheFetch(Node& n)
       
   163 	{
       
   164 		if (!Yapf().CanUseGlobalCache(n)) {
       
   165 			return Tlocal::PfNodeCacheFetch(n);
       
   166 		}
       
   167 		CacheKey key(n.GetKey());
       
   168 		bool found;
       
   169 		CachedData& item = m_global_cache.Get(key, &found);
       
   170 		Yapf().ConnectNodeToCachedData(n, item);
       
   171 		return found;
       
   172 	};
       
   173 
       
   174 	FORCEINLINE void PfNodeCacheFlush(Node& n)
       
   175 	{
       
   176 	};
       
   177 
       
   178 };
       
   179 
       
   180 
       
   181 
       
   182 
       
   183 #endif /* YAPF_COSTCACHE_HPP */