View Single Post
Old Sep 5th, 2007, 8:04 PM   #8
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 925
Rep Power: 4 lectricpharaoh will become famous soon enough
Quote:
Originally Posted by kruptof
En-queue items as normal (using the delay time not the due time), set the timer interval to the one add the head of the queue
This won't work. This brings you full-circle to your original problem.

Picture this. You add an event that should fire after 10 seconds. You then add an event that should fire after 5 seconds, so it goes to the front of the queue. When it fires, you see the event that has a 10-second delay, and set the timer accordingly. The problem, however, is that 5 seconds have elapsed, so when the 10-second delay expires, it will have been 15 seconds. In essence, any 'lower priority' event is deferred by the amount of a higher-priority event's delay (rather, the sum of all such delays). DaWei is correct; you need to re-think your notion of priority.

This isn't to say you can't have this work- you can- but it will require extra work. Remember that since delays should progressively decrement, you will need to handle this. You either must traverse the entire queue, and update the delay field of each item, or use another mechanism. Traversing a queue like this is bad because a) it incurs O(N) performance overhead, and b) 'traversing' in this manner is not an operation associated with a queue ADT. Rather, you should stick to enqueue, dequeue, and support methods/properties such as peek, isEmpty, etc. If you can iterate through it without dequeuing elements, then it's a list, not a queue.

One mechanism you could use is to maintain an adjustment factor (let's call it delta); delta is initially zero. When the timer fires, you handle the event at the front of the queue, and add its delay to delta. You then peek at the next item, subtract delta, and handle it if the result is zero or less, repeating as necessary. Once all such events are handled, you initialize the timer with the difference between delta and the front of queue's delay, and wait for the next timer firing. This approach, to me, is more complicated than my initial suggestion in this thread, as it requires tracking more state information.

My initial suggestion was aimed at getting around the 'delays not adjusting as time goes by' problem. If you store the delay, you need to adjust it in some manner, as described above. If you store the due time, you can calculate the delay as the difference between the due time and the current time. Thus, you don't need to continuously adjust your delays; since they are expressed as a relationship between an automagically updating value (DateTime.Now) and a fixed value, they update automagically themselves. You also get deterministic behavior in that an event will only be pre-empted by an event that is due sooner (and possibly at the same time, depending on your heap implementation). This is a Good Thing (tm) as it lets you make some guarantees about event latency (subject to event-handling overhead, of course). After all, there's no point having a setup to fire an event after, say, 500 milliseconds and then have it take 30 seconds to occur.
__________________
A man's knowledge is like an expanding sphere, the surface corresponding to the boundary between the known and the unknown. As the sphere grows, so does its surface; the more a man learns, the more he realizes how much he does not know. Hence, the most ignorant man thinks he knows it all. - L. Sprague de Camp
lectricpharaoh is offline   Reply With Quote