SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_OrderedChannelHeap.h
Go to the documentation of this file.
1 /*
2 * Original work: 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 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
20
21
22 #ifndef __RAKNET_ORDERED_CHANNEL_HEAP_H
23 #define __RAKNET_ORDERED_CHANNEL_HEAP_H
24
25 #include "DS_Heap.h"
26 #include "DS_Map.h"
27 #include "DS_Queue.h"
28 #include "Export.h"
29 #include "assert.h"
30 #include "Rand.h"
31
34 namespace DataStructures
35 {
36 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> >
37 class RAK_DLL_EXPORT OrderedChannelHeap
38 {
39 public:
40 static void IMPLEMENT_DEFAULT_COMPARISON(void) {DataStructures::defaultMapKeyComparison<channel_key_type>(channel_key_type(),channel_key_type());}
41
42 OrderedChannelHeap();
43 ~OrderedChannelHeap();
44 void Push(const channel_key_type &channelID, const heap_data_type &data);
45 void PushAtHead(const unsigned index, const channel_key_type &channelID, const heap_data_type &data);
46 heap_data_type Pop(const unsigned startingIndex=0);
47 heap_data_type Peek(const unsigned startingIndex) const;
48 void AddChannel(const channel_key_type &channelID, const double weight);
49 void RemoveChannel(channel_key_type channelID);
50 void Clear(void);
51 heap_data_type& operator[] ( const unsigned int position ) const;
52 unsigned ChannelSize(const channel_key_type &channelID);
53 unsigned Size(void) const;
54
55 struct QueueAndWeight
56 {
57 DataStructures::Queue<double> randResultQueue;
58 double weight;
59 bool signalDeletion;
60 };
61
62 struct HeapChannelAndData
63 {
64 HeapChannelAndData() {}
65 HeapChannelAndData(const channel_key_type &_channel, const heap_data_type &_data) : data(_data), channel(_channel) {}
66 heap_data_type data;
67 channel_key_type channel;
68 };
69
70 protected:
71 DataStructures::Map<channel_key_type, QueueAndWeight*, channel_key_comparison_func> map;
72 DataStructures::Heap<double, HeapChannelAndData, true> heap;
73 void GreatestRandResult(void);
74 };
75
76 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
77 OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::OrderedChannelHeap()
78 {
79 }
80
81 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
82 OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::~OrderedChannelHeap()
83 {
84 Clear();
85 }
86
87 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
88 void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Push(const channel_key_type &channelID, const heap_data_type &data)
89 {
90 PushAtHead(MAX_UNSIGNED_LONG, channelID, data);
91 }
92
93 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
94 void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::GreatestRandResult(void)
95 {
96 double greatest;
97 unsigned i;
98 greatest=0.0;
99 for (i=0; i < map.Size(); i++)
100 {
101 if (map[i]->randResultQueue.Size() && map[i]->randResultQueue[0]>greatest)
102 greatest=map[i]->randResultQueue[0];
103 }
104 return greatest;
105 }
106
107 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
108 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)
109 {
110 // If an assert hits here then this is an unknown channel. Call AddChannel first.
111 QueueAndWeight *queueAndWeight=map.Get(channelID);
112 double maxRange, minRange, rnd;
113 if (queueAndWeight->randResultQueue.Size()==0)
114 {
115 // Set maxRange to the greatest random number waiting to be returned, rather than 1.0 necessarily
116 // This is so weights are scaled similarly among channels. For example, if the head weight for a used channel was .25
117 // and then we added another channel, the new channel would need to choose between .25 and 0
118 // 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
119 maxRange=GreatestRandResult();
120 if (maxRange==0.0)
121 maxRange=1.0;
122 minRange=0.0;
123 }
124 else if (index >= queueAndWeight->randResultQueue.Size())
125 {
126 maxRange=queueAndWeight->randResultQueue[queueAndWeight->randResultQueue.Size()-1]*.99999999;
127 minRange=0.0;
128 }
129 else
130 {
131 if (index==0)
132 {
133 maxRange=GreatestRandResult();
134 if (maxRange==queueAndWeight->randResultQueue[0])
135 maxRange=1.0;
136 }
137 else if (index >= queueAndWeight->randResultQueue.Size())
138 maxRange=queueAndWeight->randResultQueue[queueAndWeight->randResultQueue.Size()-1]*.99999999;
139 else
140 maxRange=queueAndWeight->randResultQueue[index-1]*.99999999;
141
142 minRange=maxRange=queueAndWeight->randResultQueue[index]*1.00000001;
143 }
144
145 #ifdef _DEBUG
146 RakAssert(maxRange!=0.0);
147 #endif
148 rnd=frandomMT() * (maxRange - minRange);
149 if (rnd==0.0)
150 rnd=maxRange/2.0;
151
152 if (index >= queueAndWeight->randResultQueue.Size())
153 queueAndWeight->randResultQueue.Push(rnd);
154 else
155 queueAndWeight->randResultQueue.PushAtHead(rnd, index);
156
157 heap.Push(rnd*queueAndWeight->weight, HeapChannelAndData(channelID, data));
158 }
159
160 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
161 heap_data_type OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Pop(const unsigned startingIndex)
162 {
163 RakAssert(startingIndex < heap.Size());
164
165 QueueAndWeight *queueAndWeight=map.Get(heap[startingIndex].channel);
166 if (startingIndex!=0)
167 {
168 // Ugly - have to count in the heap how many nodes have the same channel, so we know where to delete from in the queue
169 unsigned indiceCount=0;
170 unsigned i;
171 for (i=0; i < startingIndex; i++)
172 if (channel_key_comparison_func(heap[i].channel,heap[startingIndex].channel)==0)
173 indiceCount++;
174 queueAndWeight->randResultQueue.RemoveAtIndex(indiceCount);
175 }
176 else
177 {
178 // 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.
179 queueAndWeight->randResultQueue.Pop();
180 }
181
182 // Try to remove the channel after every pop, because doing so is not valid while there are elements in the list.
183 if (queueAndWeight->signalDeletion)
184 RemoveChannel(heap[startingIndex].channel);
185
186 return heap.Pop(startingIndex).data;
187 }
188
189 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
190 heap_data_type OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Peek(const unsigned startingIndex) const
191 {
192 HeapChannelAndData heapChannelAndData = heap.Peek(startingIndex);
193 return heapChannelAndData.data;
194 }
195
196 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
197 void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::AddChannel(const channel_key_type &channelID, const double weight)
198 {
199 QueueAndWeight *qaw = SLNet::OP_NEW<QueueAndWeight>( _FILE_AND_LINE_ );
200 qaw->weight=weight;
201 qaw->signalDeletion=false;
202 map.SetNew(channelID, qaw);
203 }
204
205 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
206 void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::RemoveChannel(channel_key_type channelID)
207 {
208 if (map.Has(channelID))
209 {
210 unsigned i;
211 i=map.GetIndexAtKey(channelID);
212 if (map[i]->randResultQueue.Size()==0)
213 {
214 SLNet::OP_DELETE(map[i], _FILE_AND_LINE_);
215 map.RemoveAtIndex(i);
216 }
217 else
218 {
219 // Signal this channel for deletion later, because the heap has nodes with this channel right now
220 map[i]->signalDeletion=true;
221 }
222 }
223 }
224
225 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
226 unsigned OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Size(void) const
227 {
228 return heap.Size();
229 }
230
231 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
232 heap_data_type& OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::operator[]( const unsigned int position ) const
233 {
234 return heap[position].data;
235 }
236
237
238 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
239 unsigned OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::ChannelSize(const channel_key_type &channelID)
240 {
241 QueueAndWeight *queueAndWeight=map.Get(channelID);
242 return queueAndWeight->randResultQueue.Size();
243 }
244
245 template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
246 void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Clear(void)
247 {
248 unsigned i;
249 for (i=0; i < map.Size(); i++)
250 SLNet::OP_DELETE(map[i], _FILE_AND_LINE_);
251 map.Clear(_FILE_AND_LINE_);
252 heap.Clear(_FILE_AND_LINE_);
253 }
254 }
255
256 #endif