use std::cell::RefCell;
use std::collections::VecDeque;
use std::iter::FromIterator;
use std::rc::Rc;
use super::JobCostModel;
use crate::time::Service;
#[derive(Clone, Debug)]
pub struct Curve {
wcet_of_n_jobs: Vec<Service>,
}
impl Curve {
pub fn new(wcet_of_n_jobs: Vec<Service>) -> Self {
Curve { wcet_of_n_jobs }
}
}
impl JobCostModel for Curve {
fn cost_of_jobs(&self, n: usize) -> Service {
if !self.wcet_of_n_jobs.is_empty() && n > 0 {
let x = n / self.wcet_of_n_jobs.len();
let y = n % self.wcet_of_n_jobs.len();
let prefix = if x > 0 {
self.wcet_of_n_jobs[self.wcet_of_n_jobs.len() - 1] * x as u64
} else {
Service::none()
};
let suffix = if y > 0 {
self.wcet_of_n_jobs[y - 1]
} else {
Service::none()
};
prefix + suffix
} else {
Service::none()
}
}
fn job_cost_iter<'a>(&'a self) -> Box<dyn Iterator<Item = Service> + 'a> {
Box::new((1..).map(move |n| self.cost_of_jobs(n) - self.cost_of_jobs(n - 1)))
}
fn least_wcet(&self, n: usize) -> Service {
if n > 0 {
let mut least = self.wcet_of_n_jobs[0];
for i in 1..self.wcet_of_n_jobs.len().min(n) {
least = least.min(self.wcet_of_n_jobs[i] - self.wcet_of_n_jobs[i - 1])
}
least
} else {
Service::none()
}
}
}
impl Curve {
pub fn from_trace(job_costs: impl Iterator<Item = Service>, max_n: usize) -> Curve {
let mut cost_of = Vec::with_capacity(max_n);
let mut window: VecDeque<Service> = VecDeque::with_capacity(max_n + 1);
for c in job_costs {
window.push_back(c);
if window.len() > max_n {
window.pop_front();
}
let mut total_cost = Service::none();
for (i, k) in window.iter().enumerate() {
total_cost += *k;
if cost_of.len() <= i {
cost_of.push(total_cost)
} else {
cost_of[i] = cost_of[i].max(total_cost)
}
}
}
Curve {
wcet_of_n_jobs: cost_of,
}
}
fn extrapolate_next(&self) -> Service {
let n = self.wcet_of_n_jobs.len();
assert!(n >= 2);
(0..=(n / 2))
.map(|k| self.wcet_of_n_jobs[k] + self.wcet_of_n_jobs[n - k - 1])
.min()
.unwrap()
}
pub fn extrapolate(&mut self, n: usize) {
if self.wcet_of_n_jobs.len() >= 3 {
while self.wcet_of_n_jobs.len() < n - 1 {
self.wcet_of_n_jobs.push(self.extrapolate_next())
}
}
}
}
impl FromIterator<Service> for Curve {
fn from_iter<I: IntoIterator<Item = Service>>(iter: I) -> Curve {
let mut wcets: Vec<Service> = iter.into_iter().collect();
for i in 1..wcets.len() {
wcets[i] = wcets[i].max(wcets[i - 1]);
}
Curve::new(wcets)
}
}
#[derive(Clone, Debug)]
pub struct ExtrapolatingCurve {
prefix: Rc<RefCell<Curve>>,
}
impl ExtrapolatingCurve {
pub fn new(costfn: Curve) -> Self {
ExtrapolatingCurve {
prefix: Rc::new(RefCell::new(costfn)),
}
}
}
impl JobCostModel for ExtrapolatingCurve {
fn cost_of_jobs(&self, n: usize) -> Service {
let mut costfn = self.prefix.borrow_mut();
costfn.extrapolate(n + 1);
costfn.cost_of_jobs(n)
}
fn job_cost_iter<'a>(&'a self) -> Box<dyn Iterator<Item = Service> + 'a> {
Box::new((1..).map(move |n| self.cost_of_jobs(n) - self.cost_of_jobs(n - 1)))
}
fn least_wcet(&self, n: usize) -> Service {
self.prefix.borrow().least_wcet(n)
}
}