/** * Creates a new FuzzyEvent, Schedules it and returns it * @param todo the method to call * @param from_now_ms the TimeSpan from now to call the method * @param latency_ms the acceptable latency for this call in milliseconds */ public FuzzyEvent DoAt(System.Action <DateTime> todo, DateTime at, int latency_ms) { DateTime end = at + new TimeSpan(0, 0, 0, 0, latency_ms); FuzzyEvent new_event = new FuzzyEvent(todo, at, end); Schedule(new_event); return(new_event); }
public void Schedule(FuzzyEvent e) { #if BRUNET_SIMULATOR int delay = (int)(e.End - DateTime.UtcNow).TotalMilliseconds; SimpleTimer st = new SimpleTimer(FuzzyEventRunner, e, delay, 0); st.Start(); #else _incoming_events.Enqueue(e); #endif }
protected static void FuzzyEventRunner(object o) { FuzzyEvent fe = o as FuzzyEvent; if (o == null) { throw new Exception("o is not a FuzzyEvent!"); } fe.TryRun(DateTime.UtcNow); }
/** * Creates a new FuzzyEvent, Schedules it and returns it * @param todo the method to call * @param from_now_ms the TimeSpan from now to call the method in milliseconds * @param latency_ms the acceptable latency for this call in milliseconds */ public FuzzyEvent DoAfter(System.Action <DateTime> todo, int from_now_ms, int latency_ms) { DateTime start = DateTime.UtcNow + new TimeSpan(0, 0, 0, 0, from_now_ms); DateTime end = start + new TimeSpan(0, 0, 0, 0, latency_ms); FuzzyEvent new_event = new FuzzyEvent(todo, start, end); Schedule(new_event); return(new_event); }
/** * There can only safely be one of these threads running */ protected void AnnounceThread() { Brunet.Util.FuzzyEvent fe = null; try { int millisec_timeout = 5000; //log every 5 seconds. IAction queue_item = null; bool timedout = false; if (ProtocolLog.Monitor.Enabled) { IAction log_act = new LogAction(_packet_queue); Action <DateTime> log_todo = delegate(DateTime dt) { EnqueueAction(log_act); }; fe = Brunet.Util.FuzzyTimer.Instance.DoEvery(log_todo, millisec_timeout, millisec_timeout / 2); } while (1 == _running) { queue_item = _packet_queue.Dequeue(millisec_timeout, out timedout); if (!timedout) { _current_action = queue_item; queue_item.Start(); } } } catch (System.InvalidOperationException x) { //This is thrown when Dequeue is called on an empty queue //which happens when the BlockingQueue is closed, which //happens on Disconnect if (1 == _running) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, String.Format( "Running in AnnounceThread got Exception: {0}", x)); } } catch (Exception x) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, String.Format( "ERROR: Exception in AnnounceThread: {0}", x)); } finally { //Make sure we stop logging: if (fe != null) { fe.TryCancel(); } } ProtocolLog.Write(ProtocolLog.Monitor, String.Format("Node: {0} leaving AnnounceThread", this.Address)); }
protected void TimerThread() { Heap <FuzzyEvent> events = new Heap <FuzzyEvent>(); List <FuzzyEvent> next_todos = new List <FuzzyEvent>(); Interval <DateTime> next_schedule_int = null; int wait_interval = -1; bool run = true; bool timedout; while (run) { FuzzyEvent fe = _incoming_events.Dequeue(wait_interval, out timedout); if (!timedout) { //We got a new event if (fe != null) { events.Add(fe); } else { //Got a null event, that means stop: break; } } DateTime now = DateTime.UtcNow; /* * Since we've already been awakened, let's check to see if we can run: */ if (next_schedule_int != null) { if (next_schedule_int.CompareTo(now) <= 0) { //We are safe to go ahead and run: Interlocked.Exchange(ref _last_run, now.Ticks); foreach (FuzzyEvent feitem in next_todos) { try { feitem.TryRun(now); } catch (Exception x) { Console.WriteLine(x); //Something bad happened } } //Now reset and reschedule below: next_todos.Clear(); next_schedule_int = null; } else { //It's not yet time to run. } } //Time to schedule the next wait: Interval <DateTime> overlap; do { if (events.Count > 0) { overlap = events.Peek(); if (next_schedule_int != null) { //We already have something scheduled: var new_overlap = next_schedule_int.Intersection(overlap); if (new_overlap == null) { if (overlap.CompareTo(next_schedule_int) <= 0) { /* * If there is no overlap, but next_schedule_int is after, * overlap, we need to reorder things: */ //Put the next_todos back: var new_next = events.Pop(); foreach (FuzzyEvent fev in next_todos) { events.Add(fev); } next_todos.Clear(); next_todos.Add(new_next); next_schedule_int = new_next; overlap = new_next; } else { //we'll deal with overlap later: overlap = null; } } else { //There is an overlap //We can combine the old and new event: overlap = new_overlap; next_schedule_int = overlap; next_todos.Add(events.Pop()); } } else { //There was nothing scheduled: next_schedule_int = overlap; next_todos.Add(events.Pop()); } } else { overlap = null; } } while(overlap != null); if (next_schedule_int != null) { //Wait as long as possible, we may be able to combine later: TimeSpan to_wait = next_schedule_int.End - now; wait_interval = (int)to_wait.TotalMilliseconds; if (wait_interval < 0) { //Well, we should be able to go ahead and run, so do it: wait_interval = 0; } } else { //Nothing to do, just wait for the next scheduled operation wait_interval = -1; } } }