DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Git (74cd81b8ce)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use script_traits::{TimerEvent, TimerEventRequest, TimerSchedulerMsg};
use std::cmp::{self, Ord};
use std::collections::BinaryHeap;
use std::time::{Duration, Instant};

pub struct TimerScheduler(BinaryHeap<ScheduledEvent>);

struct ScheduledEvent {
    request: TimerEventRequest,
    for_time: Instant,
}

impl Ord for ScheduledEvent {
    fn cmp(&self, other: &ScheduledEvent) -> cmp::Ordering {
        self.for_time.cmp(&other.for_time).reverse()
    }
}

impl PartialOrd for ScheduledEvent {
    fn partial_cmp(&self, other: &ScheduledEvent) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for ScheduledEvent {}
impl PartialEq for ScheduledEvent {
    fn eq(&self, other: &ScheduledEvent) -> bool {
        self as *const ScheduledEvent == other as *const ScheduledEvent
    }
}

impl TimerScheduler {
    pub fn new() -> Self {
        TimerScheduler(BinaryHeap::<ScheduledEvent>::new())
    }

    /// Dispatch any events whose due time is past,
    /// and return a timeout corresponding to the earliest scheduled event, if any.
    pub fn check_timers(&mut self) -> Option<Duration> {
        let now = Instant::now();
        loop {
            match self.0.peek() {
                // Dispatch the event if its due time is past
                Some(event) if event.for_time <= now => {
                    let TimerEventRequest(ref sender, source, id, _) = event.request;
                    let _ = sender.send(TimerEvent(source, id));
                },
                // Do not schedule a timeout.
                None => return None,
                // Schedule a timeout for the earliest event.
                Some(event) => return Some(event.for_time - now),
            }
            // Remove the event from the priority queue
            // (Note this only executes when the first event has been dispatched).
            self.0.pop();
        }
    }

    /// Handle an incoming timer request.
    pub fn handle_timer_request(&mut self, request: TimerSchedulerMsg) {
        let TimerEventRequest(_, _, _, delay) = request.0;
        let schedule = Instant::now() + Duration::from_millis(delay.get());
        let event = ScheduledEvent {
            request: request.0,
            for_time: schedule,
        };
        self.0.push(event);
    }
}