aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/IClientAPI.cs59
-rw-r--r--OpenSim/Framework/PriorityQueue.cs (renamed from OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs)132
-rw-r--r--OpenSim/Framework/Util.cs17
3 files changed, 169 insertions, 39 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index f573c32..069987b 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -572,34 +572,69 @@ namespace OpenSim.Framework
572 572
573 public class IEntityUpdate 573 public class IEntityUpdate
574 { 574 {
575 public ISceneEntity Entity; 575 private ISceneEntity m_entity;
576 public uint Flags; 576 private uint m_flags;
577 private int m_updateTime;
578
579 public ISceneEntity Entity
580 {
581 get { return m_entity; }
582 }
583
584 public uint Flags
585 {
586 get { return m_flags; }
587 }
588
589 public int UpdateTime
590 {
591 get { return m_updateTime; }
592 }
577 593
578 public virtual void Update(IEntityUpdate update) 594 public virtual void Update(IEntityUpdate update)
579 { 595 {
580 this.Flags |= update.Flags; 596 m_flags |= update.Flags;
597
598 // Use the older of the updates as the updateTime
599 if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0)
600 m_updateTime = update.UpdateTime;
581 } 601 }
582 602
583 public IEntityUpdate(ISceneEntity entity, uint flags) 603 public IEntityUpdate(ISceneEntity entity, uint flags)
584 { 604 {
585 Entity = entity; 605 m_entity = entity;
586 Flags = flags; 606 m_flags = flags;
607 m_updateTime = Util.EnvironmentTickCount();
608 }
609
610 public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime)
611 {
612 m_entity = entity;
613 m_flags = flags;
614 m_updateTime = updateTime;
587 } 615 }
588 } 616 }
589
590 617
591 public class EntityUpdate : IEntityUpdate 618 public class EntityUpdate : IEntityUpdate
592 { 619 {
593 // public ISceneEntity Entity; 620 private float m_timeDilation;
594 // public PrimUpdateFlags Flags; 621
595 public float TimeDilation; 622 public float TimeDilation
623 {
624 get { return m_timeDilation; }
625 }
596 626
597 public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) 627 public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation)
598 : base(entity,(uint)flags) 628 : base(entity, (uint)flags)
599 { 629 {
600 //Entity = entity;
601 // Flags = flags; 630 // Flags = flags;
602 TimeDilation = timedilation; 631 m_timeDilation = timedilation;
632 }
633
634 public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime)
635 : base(entity,(uint)flags,updateTime)
636 {
637 m_timeDilation = timedilation;
603 } 638 }
604 } 639 }
605 640
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index b62ec07..3e6fdaa 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -34,50 +34,81 @@ using OpenSim.Framework;
34using OpenSim.Framework.Client; 34using OpenSim.Framework.Client;
35using log4net; 35using log4net;
36 36
37namespace OpenSim.Region.ClientStack.LindenUDP 37namespace OpenSim.Framework
38{ 38{
39 public class PriorityQueue 39 public class PriorityQueue
40 { 40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 42
43 internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity); 43 public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
44 44
45 // Heap[0] for self updates 45 /// <summary>
46 // Heap[1..12] for entity updates 46 /// Total number of queues (priorities) available
47 /// </summary>
48 public const uint NumberOfQueues = 12;
47 49
48 internal const uint m_numberOfQueues = 12; 50 /// <summary>
51 /// Number of queuest (priorities) that are processed immediately
52 /// </summary.
53 public const uint NumberOfImmediateQueues = 2;
49 54
50 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues]; 55 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues];
51 private Dictionary<uint, LookupItem> m_lookupTable; 56 private Dictionary<uint, LookupItem> m_lookupTable;
57
58 // internal state used to ensure the deqeues are spread across the priority
59 // queues "fairly". queuecounts is the amount to pull from each queue in
60 // each pass. weighted towards the higher priority queues
52 private uint m_nextQueue = 0; 61 private uint m_nextQueue = 0;
62 private uint m_countFromQueue = 0;
63 private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 };
64
65 // next request is a counter of the number of updates queued, it provides
66 // a total ordering on the updates coming through the queue and is more
67 // lightweight (and more discriminating) than tick count
53 private UInt64 m_nextRequest = 0; 68 private UInt64 m_nextRequest = 0;
54 69
70 /// <summary>
71 /// Lock for enqueue and dequeue operations on the priority queue
72 /// </summary>
55 private object m_syncRoot = new object(); 73 private object m_syncRoot = new object();
56 public object SyncRoot { 74 public object SyncRoot {
57 get { return this.m_syncRoot; } 75 get { return this.m_syncRoot; }
58 } 76 }
59 77
60 internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { } 78#region constructor
79 public PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
61 80
62 internal PriorityQueue(int capacity) 81 public PriorityQueue(int capacity)
63 { 82 {
64 m_lookupTable = new Dictionary<uint, LookupItem>(capacity); 83 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
65 84
66 for (int i = 0; i < m_heaps.Length; ++i) 85 for (int i = 0; i < m_heaps.Length; ++i)
67 m_heaps[i] = new MinHeap<MinHeapItem>(capacity); 86 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
87
88 m_nextQueue = NumberOfImmediateQueues;
89 m_countFromQueue = m_queueCounts[m_nextQueue];
68 } 90 }
91#endregion Constructor
69 92
70 internal int Count 93#region PublicMethods
94 /// <summary>
95 /// Return the number of items in the queues
96 /// </summary>
97 public int Count
71 { 98 {
72 get 99 get
73 { 100 {
74 int count = 0; 101 int count = 0;
75 for (int i = 0; i < m_heaps.Length; ++i) 102 for (int i = 0; i < m_heaps.Length; ++i)
76 count += m_heaps[i].Count; 103 count += m_heaps[i].Count;
104
77 return count; 105 return count;
78 } 106 }
79 } 107 }
80 108
109 /// <summary>
110 /// Enqueue an item into the specified priority queue
111 /// </summary>
81 public bool Enqueue(uint pqueue, IEntityUpdate value) 112 public bool Enqueue(uint pqueue, IEntityUpdate value)
82 { 113 {
83 LookupItem lookup; 114 LookupItem lookup;
@@ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
91 lookup.Heap.Remove(lookup.Handle); 122 lookup.Heap.Remove(lookup.Handle);
92 } 123 }
93 124
94 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); 125 pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
95 lookup.Heap = m_heaps[pqueue]; 126 lookup.Heap = m_heaps[pqueue];
96 lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); 127 lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
97 m_lookupTable[localid] = lookup; 128 m_lookupTable[localid] = lookup;
@@ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
99 return true; 130 return true;
100 } 131 }
101 132
102 internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) 133 /// <summary>
134 /// Remove an item from one of the queues. Specifically, it removes the
135 /// oldest item from the next queue in order to provide fair access to
136 /// all of the queues
137 /// </summary>
138 public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
103 { 139 {
104 for (int i = 0; i < m_numberOfQueues; ++i) 140 // If there is anything in priority queue 0, return it first no
141 // matter what else. Breaks fairness. But very useful.
142 for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
105 { 143 {
106 // To get the fair queing, we cycle through each of the 144 if (m_heaps[iq].Count > 0)
107 // queues when finding an element to dequeue, this code
108 // assumes that the distribution of updates in the queues
109 // is polynomial, probably quadractic (eg distance of PI * R^2)
110 uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
111 if (m_heaps[h].Count > 0)
112 { 145 {
113 m_nextQueue = (uint)((h + 1) % m_numberOfQueues); 146 MinHeapItem item = m_heaps[iq].RemoveMin();
147 m_lookupTable.Remove(item.Value.Entity.LocalId);
148 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
149 value = item.Value;
114 150
115 MinHeapItem item = m_heaps[h].RemoveMin(); 151 return true;
152 }
153 }
154
155 // To get the fair queing, we cycle through each of the
156 // queues when finding an element to dequeue.
157 // We pull (NumberOfQueues - QueueIndex) items from each queue in order
158 // to give lower numbered queues a higher priority and higher percentage
159 // of the bandwidth.
160
161 // Check for more items to be pulled from the current queue
162 if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0)
163 {
164 m_countFromQueue--;
165
166 MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
167 m_lookupTable.Remove(item.Value.Entity.LocalId);
168 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
169 value = item.Value;
170
171 return true;
172 }
173
174 // Find the next non-immediate queue with updates in it
175 for (int i = 0; i < NumberOfQueues; ++i)
176 {
177 m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues);
178 m_countFromQueue = m_queueCounts[m_nextQueue];
179
180 // if this is one of the immediate queues, just skip it
181 if (m_nextQueue < NumberOfImmediateQueues)
182 continue;
183
184 if (m_heaps[m_nextQueue].Count > 0)
185 {
186 m_countFromQueue--;
187
188 MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
116 m_lookupTable.Remove(item.Value.Entity.LocalId); 189 m_lookupTable.Remove(item.Value.Entity.LocalId);
117 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); 190 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
118 value = item.Value; 191 value = item.Value;
@@ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
126 return false; 199 return false;
127 } 200 }
128 201
129 internal void Reprioritize(UpdatePriorityHandler handler) 202 /// <summary>
203 /// Reapply the prioritization function to each of the updates currently
204 /// stored in the priority queues.
205 /// </summary
206 public void Reprioritize(UpdatePriorityHandler handler)
130 { 207 {
131 MinHeapItem item; 208 MinHeapItem item;
132 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values)) 209 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
@@ -140,7 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
140 { 217 {
141 // unless the priority queue has changed, there is no need to modify 218 // unless the priority queue has changed, there is no need to modify
142 // the entry 219 // the entry
143 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); 220 pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1);
144 if (pqueue != item.PriorityQueue) 221 if (pqueue != item.PriorityQueue)
145 { 222 {
146 lookup.Heap.Remove(lookup.Handle); 223 lookup.Heap.Remove(lookup.Handle);
@@ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
161 } 238 }
162 } 239 }
163 240
241 /// <summary>
242 /// </summary>
164 public override string ToString() 243 public override string ToString()
165 { 244 {
166 string s = ""; 245 string s = "";
167 for (int i = 0; i < m_numberOfQueues; i++) 246 for (int i = 0; i < NumberOfQueues; i++)
168 { 247 s += String.Format("{0,7} ",m_heaps[i].Count);
169 if (s != "") s += ",";
170 s += m_heaps[i].Count.ToString();
171 }
172 return s; 248 return s;
173 } 249 }
174 250
251#endregion PublicMethods
252
175#region MinHeapItem 253#region MinHeapItem
176 private struct MinHeapItem : IComparable<MinHeapItem> 254 private struct MinHeapItem : IComparable<MinHeapItem>
177 { 255 {
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 5a5046e..aaa2724 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1537,6 +1537,23 @@ namespace OpenSim.Framework
1537 return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); 1537 return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
1538 } 1538 }
1539 1539
1540 // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
1541 // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount().
1542 // A positive return value indicates A occured later than B
1543 public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB)
1544 {
1545 // A, B and TC are all between 0 and 0x3fffffff
1546 int tc = EnvironmentTickCount();
1547
1548 if (tc - tcA >= 0)
1549 tcA += EnvironmentTickCountMask + 1;
1550
1551 if (tc - tcB >= 0)
1552 tcB += EnvironmentTickCountMask + 1;
1553
1554 return tcA - tcB;
1555 }
1556
1540 /// <summary> 1557 /// <summary>
1541 /// Prints the call stack at any given point. Useful for debugging. 1558 /// Prints the call stack at any given point. Useful for debugging.
1542 /// </summary> 1559 /// </summary>