Shadowrun: Awakened 29 September 2011 - Build 871
DS_OrderedChannelHeap.h
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __RAKNET_ORDERED_CHANNEL_HEAP_H
00011 #define __RAKNET_ORDERED_CHANNEL_HEAP_H
00012 
00013 #include "DS_Heap.h"
00014 #include "DS_Map.h"
00015 #include "DS_Queue.h"
00016 #include "Export.h"
00017 #include "RakAssert.h"
00018 #include "Rand.h"
00019 
00022 namespace DataStructures
00023 {
00024     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> >
00025     class RAK_DLL_EXPORT OrderedChannelHeap
00026     {
00027     public:
00028         static void IMPLEMENT_DEFAULT_COMPARISON(void) {DataStructures::defaultMapKeyComparison<channel_key_type>(channel_key_type(),channel_key_type());}
00029 
00030         OrderedChannelHeap();
00031         ~OrderedChannelHeap();
00032         void Push(const channel_key_type &channelID, const heap_data_type &data);
00033         void PushAtHead(const unsigned index, const channel_key_type &channelID, const heap_data_type &data);
00034         heap_data_type Pop(const unsigned startingIndex=0);
00035         heap_data_type Peek(const unsigned startingIndex) const;
00036         void AddChannel(const channel_key_type &channelID, const double weight);
00037         void RemoveChannel(channel_key_type channelID);
00038         void Clear(void);
00039         heap_data_type& operator[] ( const unsigned int position ) const;
00040         unsigned ChannelSize(const channel_key_type &channelID);
00041         unsigned Size(void) const;
00042 
00043         struct QueueAndWeight
00044         {
00045             DataStructures::Queue<double> randResultQueue;
00046             double weight;
00047             bool signalDeletion;
00048         };
00049 
00050         struct HeapChannelAndData
00051         {
00052             HeapChannelAndData() {}
00053             HeapChannelAndData(const channel_key_type &_channel, const heap_data_type &_data) : data(_data), channel(_channel) {}
00054             heap_data_type data;
00055             channel_key_type channel;
00056         };
00057 
00058     protected:
00059         DataStructures::Map<channel_key_type, QueueAndWeight*, channel_key_comparison_func> map;
00060         DataStructures::Heap<double, HeapChannelAndData, true> heap;
00061         void GreatestRandResult(void);
00062     };
00063 
00064     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00065         OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::OrderedChannelHeap()
00066     {
00067     }
00068 
00069     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00070         OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::~OrderedChannelHeap()
00071     {
00072         Clear();
00073     }
00074 
00075     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00076     void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Push(const channel_key_type &channelID, const heap_data_type &data)
00077     {
00078         PushAtHead(MAX_UNSIGNED_LONG, channelID, data);
00079     }
00080 
00081     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00082     void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::GreatestRandResult(void)
00083     {
00084         double greatest;
00085         unsigned i;
00086         greatest=0.0;
00087         for (i=0; i < map.Size(); i++)
00088         {
00089             if (map[i]->randResultQueue.Size() && map[i]->randResultQueue[0]>greatest)
00090                 greatest=map[i]->randResultQueue[0];
00091         }
00092         return greatest;
00093     }
00094 
00095     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00096     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)
00097     {
00098         // If an assert hits here then this is an unknown channel.  Call AddChannel first.
00099         QueueAndWeight *queueAndWeight=map.Get(channelID);
00100         double maxRange, minRange, rnd;
00101         if (queueAndWeight->randResultQueue.Size()==0)
00102         {
00103             // Set maxRange to the greatest random number waiting to be returned, rather than 1.0 necessarily
00104             // This is so weights are scaled similarly among channels.  For example, if the head weight for a used channel was .25
00105             // and then we added another channel, the new channel would need to choose between .25 and 0
00106             // 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
00107             maxRange=GreatestRandResult();
00108             if (maxRange==0.0)
00109                 maxRange=1.0;
00110             minRange=0.0;
00111         }
00112         else if (index >= queueAndWeight->randResultQueue.Size())
00113         {
00114             maxRange=queueAndWeight->randResultQueue[queueAndWeight->randResultQueue.Size()-1]*.99999999;
00115             minRange=0.0;
00116         }
00117         else
00118         {
00119             if (index==0)
00120             {
00121                 maxRange=GreatestRandResult();
00122                 if (maxRange==queueAndWeight->randResultQueue[0])
00123                     maxRange=1.0;
00124             }
00125             else if (index >= queueAndWeight->randResultQueue.Size())
00126                 maxRange=queueAndWeight->randResultQueue[queueAndWeight->randResultQueue.Size()-1]*.99999999;
00127             else
00128                 maxRange=queueAndWeight->randResultQueue[index-1]*.99999999;
00129 
00130             minRange=maxRange=queueAndWeight->randResultQueue[index]*1.00000001;
00131         }
00132         
00133 #ifdef _DEBUG
00134         RakAssert(maxRange!=0.0);
00135 #endif
00136         rnd=frandomMT() * (maxRange - minRange);
00137         if (rnd==0.0)
00138             rnd=maxRange/2.0;
00139 
00140         if (index >= queueAndWeight->randResultQueue.Size())
00141             queueAndWeight->randResultQueue.Push(rnd);
00142         else
00143             queueAndWeight->randResultQueue.PushAtHead(rnd, index);
00144 
00145         heap.Push(rnd*queueAndWeight->weight, HeapChannelAndData(channelID, data));
00146     }
00147 
00148     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00149     heap_data_type OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Pop(const unsigned startingIndex)
00150     {
00151         RakAssert(startingIndex < heap.Size());
00152 
00153         QueueAndWeight *queueAndWeight=map.Get(heap[startingIndex].channel);
00154         if (startingIndex!=0)
00155         {
00156             // Ugly - have to count in the heap how many nodes have the same channel, so we know where to delete from in the queue
00157             unsigned indiceCount=0;
00158             unsigned i;
00159             for (i=0; i < startingIndex; i++)
00160                 if (channel_key_comparison_func(heap[i].channel,heap[startingIndex].channel)==0)
00161                     indiceCount++;
00162             queueAndWeight->randResultQueue.RemoveAtIndex(indiceCount);
00163         }
00164         else
00165         {
00166             // 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.
00167             queueAndWeight->randResultQueue.Pop();
00168         }
00169 
00170         // Try to remove the channel after every pop, because doing so is not valid while there are elements in the list.
00171         if (queueAndWeight->signalDeletion)
00172             RemoveChannel(heap[startingIndex].channel);
00173 
00174         return heap.Pop(startingIndex).data;
00175     }
00176 
00177     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00178     heap_data_type OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Peek(const unsigned startingIndex) const
00179     {
00180         HeapChannelAndData heapChannelAndData = heap.Peek(startingIndex);
00181         return heapChannelAndData.data;
00182     }
00183 
00184     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00185     void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::AddChannel(const channel_key_type &channelID, const double weight)
00186     {
00187         QueueAndWeight *qaw = RakNet::OP_NEW<QueueAndWeight>( _FILE_AND_LINE_ );
00188         qaw->weight=weight;
00189         qaw->signalDeletion=false;
00190         map.SetNew(channelID, qaw);
00191     }
00192 
00193     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00194         void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::RemoveChannel(channel_key_type channelID)
00195     {
00196         if (map.Has(channelID))
00197         {
00198             unsigned i;
00199             i=map.GetIndexAtKey(channelID);
00200             if (map[i]->randResultQueue.Size()==0)
00201             {
00202                 RakNet::OP_DELETE(map[i], _FILE_AND_LINE_);
00203                 map.RemoveAtIndex(i);
00204             }
00205             else
00206             {
00207                 // Signal this channel for deletion later, because the heap has nodes with this channel right now
00208                 map[i]->signalDeletion=true;
00209             }
00210         }
00211     }
00212 
00213     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00214         unsigned OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Size(void) const
00215     {
00216         return heap.Size();
00217     }
00218 
00219     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00220         heap_data_type& OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::operator[]( const unsigned int position ) const
00221     {
00222         return heap[position].data;
00223     }
00224 
00225 
00226     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00227         unsigned OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::ChannelSize(const channel_key_type &channelID)
00228     {
00229         QueueAndWeight *queueAndWeight=map.Get(channelID);
00230         return queueAndWeight->randResultQueue.Size();
00231     }
00232 
00233     template <class channel_key_type, class heap_data_type, int (*channel_key_comparison_func)(const channel_key_type&, const channel_key_type&)>
00234         void OrderedChannelHeap<channel_key_type, heap_data_type, channel_key_comparison_func>::Clear(void)
00235     {
00236         unsigned i;
00237         for (i=0; i < map.Size(); i++)
00238             RakNet::OP_DELETE(map[i], _FILE_AND_LINE_);
00239         map.Clear(_FILE_AND_LINE_);
00240         heap.Clear(_FILE_AND_LINE_);
00241     }
00242 }
00243 
00244 #endif

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net