DS_OrderedChannelHeap.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file DS_OrderedChannelHeap.h
  11. /// \internal
  12. /// \brief Ordered Channel Heap . This is a heap where you add to it on multiple ordered channels, with each channel having a different weight.
  13. ///
  14. #ifndef __RAKNET_ORDERED_CHANNEL_HEAP_H
  15. #define __RAKNET_ORDERED_CHANNEL_HEAP_H
  16. #include "DS_Heap.h"
  17. #include "DS_Map.h"
  18. #include "DS_Queue.h"
  19. #include "Export.h"
  20. #include "RakAssert.h"
  21. #include "Rand.h"
  22. /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
  23. /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
  24. namespace DataStructures
  25. {
  26. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)=defaultMapKeyComparison<channel_key_type> >
  27. class RAK_DLL_EXPORT OrderedChannelHeap
  28. {
  29. public:
  30. static void IMPLEMENT_DEFAULT_COMPARISON(void) {DataStructures::defaultMapKeyComparison<channel_key_type>(channel_key_type(),channel_key_type());}
  31. OrderedChannelHeap();
  32. ~OrderedChannelHeap();
  33. void Push(const channel_key_type &channelID, const heap_data_type &data);
  34. void PushAtHead(const unsigned index, const channel_key_type &channelID, const heap_data_type &data);
  35. heap_data_type Pop(const unsigned startingIndex=0);
  36. heap_data_type Peek(const unsigned startingIndex) const;
  37. void AddChannel(const channel_key_type &channelID, const double weight);
  38. void RemoveChannel(channel_key_type channelID);
  39. void Clear(void);
  40. heap_data_type& operator[] ( const unsigned int position ) const;
  41. unsigned ChannelSize(const channel_key_type &channelID);
  42. unsigned Size(void) const;
  43. struct QueueAndWeight
  44. {
  45. DataStructures::Queue<double> randResultQueue;
  46. double weight;
  47. bool signalDeletion;
  48. };
  49. struct HeapChannelAndData
  50. {
  51. HeapChannelAndData() {}
  52. HeapChannelAndData(const channel_key_type &_channel, const heap_data_type &_data) : data(_data), channel(_channel) {}
  53. heap_data_type data;
  54. channel_key_type channel;
  55. };
  56. protected:
  57. DataStructures::Map<channel_key_type, QueueAndWeight*, channel_key_comparison_func> map;
  58. DataStructures::Heap<double, HeapChannelAndData, true> heap;
  59. void GreatestRandResult(void);
  60. };
  61. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  62. OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::OrderedChannelHeap()
  63. {
  64. }
  65. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  66. OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::~OrderedChannelHeap()
  67. {
  68. Clear();
  69. }
  70. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  71. void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Push(const channel_key_type &channelID, const heap_data_type &data)
  72. {
  73. PushAtHead(MAX_UNSIGNED_LONG, channelID, data);
  74. }
  75. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  76. void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::GreatestRandResult(void)
  77. {
  78. double greatest;
  79. unsigned i;
  80. greatest=0.0;
  81. for (i=0; i < map.Size(); i++)
  82. {
  83. if (map[i]->randResultQueue.Size() && map[i]->randResultQueue[0]>greatest)
  84. greatest=map[i]->randResultQueue[0];
  85. }
  86. return greatest;
  87. }
  88. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  89. void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::PushAtHead(const unsigned index, const channel_key_type &channelID, const heap_data_type &data)
  90. {
  91. // If an assert hits here then this is an unknown channel. Call AddChannel first.
  92. QueueAndWeight *queueAndWeight=map.Get(channelID);
  93. double maxRange, minRange, rnd;
  94. if (queueAndWeight->randResultQueue.Size()==0)
  95. {
  96. // Set maxRange to the greatest random number waiting to be returned, rather than 1.0 necessarily
  97. // This is so weights are scaled similarly among channels. For example, if the head weight for a used channel was .25
  98. // and then we added another channel, the new channel would need to choose between .25 and 0
  99. // If we chose between 1.0 and 0, it would be 1/.25 (4x) more likely to be at the head of the heap than it should be
  100. maxRange=GreatestRandResult();
  101. if (maxRange==0.0)
  102. maxRange=1.0;
  103. minRange=0.0;
  104. }
  105. else if (index >= queueAndWeight->randResultQueue.Size())
  106. {
  107. maxRange=queueAndWeight->randResultQueue[queueAndWeight->randResultQueue.Size()-1]*.99999999;
  108. minRange=0.0;
  109. }
  110. else
  111. {
  112. if (index==0)
  113. {
  114. maxRange=GreatestRandResult();
  115. if (maxRange==queueAndWeight->randResultQueue[0])
  116. maxRange=1.0;
  117. }
  118. else if (index >= queueAndWeight->randResultQueue.Size())
  119. maxRange=queueAndWeight->randResultQueue[queueAndWeight->randResultQueue.Size()-1]*.99999999;
  120. else
  121. maxRange=queueAndWeight->randResultQueue[index-1]*.99999999;
  122. minRange=maxRange=queueAndWeight->randResultQueue[index]*1.00000001;
  123. }
  124. #ifdef _DEBUG
  125. RakAssert(maxRange!=0.0);
  126. #endif
  127. rnd=frandomMT() * (maxRange - minRange);
  128. if (rnd==0.0)
  129. rnd=maxRange/2.0;
  130. if (index >= queueAndWeight->randResultQueue.Size())
  131. queueAndWeight->randResultQueue.Push(rnd);
  132. else
  133. queueAndWeight->randResultQueue.PushAtHead(rnd, index);
  134. heap.Push(rnd*queueAndWeight->weight, HeapChannelAndData(channelID, data));
  135. }
  136. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  137. heap_data_type OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Pop(const unsigned startingIndex)
  138. {
  139. RakAssert(startingIndex < heap.Size());
  140. QueueAndWeight *queueAndWeight=map.Get(heap[startingIndex].channel);
  141. if (startingIndex!=0)
  142. {
  143. // Ugly - have to count in the heap how many nodes have the same channel, so we know where to delete from in the queue
  144. unsigned indiceCount=0;
  145. unsigned i;
  146. for (i=0; i < startingIndex; i++)
  147. if (channel_key_comparison_func(heap[i].channel,heap[startingIndex].channel)==0)
  148. indiceCount++;
  149. queueAndWeight->randResultQueue.RemoveAtIndex(indiceCount);
  150. }
  151. else
  152. {
  153. // TODO - ordered channel heap uses progressively lower values as items are inserted. But this won't give relative ordering among channels. I have to renormalize after every pop.
  154. queueAndWeight->randResultQueue.Pop();
  155. }
  156. // Try to remove the channel after every pop, because doing so is not valid while there are elements in the list.
  157. if (queueAndWeight->signalDeletion)
  158. RemoveChannel(heap[startingIndex].channel);
  159. return heap.Pop(startingIndex).data;
  160. }
  161. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  162. heap_data_type OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Peek(const unsigned startingIndex) const
  163. {
  164. HeapChannelAndData heapChannelAndData = heap.Peek(startingIndex);
  165. return heapChannelAndData.data;
  166. }
  167. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  168. void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::AddChannel(const channel_key_type &channelID, const double weight)
  169. {
  170. QueueAndWeight *qaw = RakNet::OP_NEW<QueueAndWeight>( _FILE_AND_LINE_ );
  171. qaw->weight=weight;
  172. qaw->signalDeletion=false;
  173. map.SetNew(channelID, qaw);
  174. }
  175. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  176. void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::RemoveChannel(channel_key_type channelID)
  177. {
  178. if (map.Has(channelID))
  179. {
  180. unsigned i;
  181. i=map.GetIndexAtKey(channelID);
  182. if (map[i]->randResultQueue.Size()==0)
  183. {
  184. RakNet::OP_DELETE(map[i], _FILE_AND_LINE_);
  185. map.RemoveAtIndex(i);
  186. }
  187. else
  188. {
  189. // Signal this channel for deletion later, because the heap has nodes with this channel right now
  190. map[i]->signalDeletion=true;
  191. }
  192. }
  193. }
  194. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  195. unsigned OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Size(void) const
  196. {
  197. return heap.Size();
  198. }
  199. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  200. heap_data_type& OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::operator[]( const unsigned int position ) const
  201. {
  202. return heap[position].data;
  203. }
  204. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  205. unsigned OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::ChannelSize(const channel_key_type &channelID)
  206. {
  207. QueueAndWeight *queueAndWeight=map.Get(channelID);
  208. return queueAndWeight->randResultQueue.Size();
  209. }
  210. template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
  211. void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Clear(void)
  212. {
  213. unsigned i;
  214. for (i=0; i < map.Size(); i++)
  215. RakNet::OP_DELETE(map[i], _FILE_AND_LINE_);
  216. map.Clear(_FILE_AND_LINE_);
  217. heap.Clear(_FILE_AND_LINE_);
  218. }
  219. }
  220. #endif
粤ICP备19079148号