00001 /* $Id: nodelist.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 NODELIST_HPP 00013 #define NODELIST_HPP 00014 00015 #include "../../misc/array.hpp" 00016 #include "../../misc/hashtable.hpp" 00017 #include "../../misc/binaryheap.hpp" 00018 00022 template <class Titem_, int Thash_bits_open_, int Thash_bits_closed_> 00023 class CNodeList_HashTableT { 00024 public: 00026 typedef Titem_ Titem; 00028 typedef typename Titem_::Key Key; 00030 typedef SmallArray<Titem_, 65536, 256> CItemArray; 00032 typedef CHashTableT<Titem_, Thash_bits_open_ > COpenList; 00034 typedef CHashTableT<Titem_, Thash_bits_closed_> CClosedList; 00036 typedef CBinaryHeapT<Titem_> CPriorityQueue; 00037 00038 protected: 00040 CItemArray m_arr; 00042 COpenList m_open; 00044 CClosedList m_closed; 00046 CPriorityQueue m_open_queue; 00048 Titem *m_new_node; 00049 public: 00051 CNodeList_HashTableT() 00052 : m_open_queue(204800) 00053 { 00054 m_new_node = NULL; 00055 } 00056 00058 ~CNodeList_HashTableT() 00059 { 00060 } 00061 00063 FORCEINLINE int OpenCount() 00064 { 00065 return m_open.Count(); 00066 } 00067 00069 FORCEINLINE int ClosedCount() 00070 { 00071 return m_closed.Count(); 00072 } 00073 00075 FORCEINLINE Titem_ *CreateNewNode() 00076 { 00077 if (m_new_node == NULL) m_new_node = m_arr.AppendC(); 00078 return m_new_node; 00079 } 00080 00082 FORCEINLINE void FoundBestNode(Titem_& item) 00083 { 00084 /* for now it is enough to invalidate m_new_node if it is our given node */ 00085 if (&item == m_new_node) { 00086 m_new_node = NULL; 00087 } 00088 /* TODO: do we need to store best nodes found in some extra list/array? Probably not now. */ 00089 } 00090 00092 FORCEINLINE void InsertOpenNode(Titem_& item) 00093 { 00094 assert(m_closed.Find(item.GetKey()) == NULL); 00095 m_open.Push(item); 00096 /* TODO: check if m_open_queue is not full */ 00097 assert(!m_open_queue.IsFull()); 00098 m_open_queue.Push(item); 00099 if (&item == m_new_node) { 00100 m_new_node = NULL; 00101 } 00102 } 00103 00105 FORCEINLINE Titem_ *GetBestOpenNode() 00106 { 00107 if (!m_open_queue.IsEmpty()) { 00108 Titem_& item = m_open_queue.GetHead(); 00109 return &item; 00110 } 00111 return NULL; 00112 } 00113 00115 FORCEINLINE Titem_ *PopBestOpenNode() 00116 { 00117 if (!m_open_queue.IsEmpty()) { 00118 Titem_& item = m_open_queue.PopHead(); 00119 m_open.Pop(item); 00120 return &item; 00121 } 00122 return NULL; 00123 } 00124 00126 FORCEINLINE Titem_ *FindOpenNode(const Key& key) 00127 { 00128 Titem_ *item = m_open.Find(key); 00129 return item; 00130 } 00131 00133 FORCEINLINE Titem_& PopOpenNode(const Key& key) 00134 { 00135 Titem_& item = m_open.Pop(key); 00136 int idxPop = m_open_queue.FindLinear(item); 00137 m_open_queue.RemoveByIdx(idxPop); 00138 return item; 00139 } 00140 00142 FORCEINLINE void InsertClosedNode(Titem_& item) 00143 { 00144 assert(m_open.Find(item.GetKey()) == NULL); 00145 m_closed.Push(item); 00146 } 00147 00149 FORCEINLINE Titem_ *FindClosedNode(const Key& key) 00150 { 00151 Titem_ *item = m_closed.Find(key); 00152 return item; 00153 } 00154 00155 FORCEINLINE int TotalCount() {return m_arr.Length();} 00156 FORCEINLINE Titem_& ItemAt(int idx) {return m_arr[idx];} 00157 00158 template <class D> void Dump(D &dmp) const 00159 { 00160 dmp.WriteStructT("m_arr", &m_arr); 00161 } 00162 }; 00163 00164 #endif /* NODELIST_HPP */