use rand::SeedableRng;
use rand::rngs::StdRng;
use rand::prelude::SliceRandom;
use crate::allocator::{Allocator, Request, GrantedRequests, AllocatorBuilderArgument};
use crate::config_parser::ConfigurationValue;
use crate::match_object_panic;
#[derive(Default, Clone)]
struct Resource {
client: Option<usize>,
}
#[derive(Default, Clone)]
struct Client {
resource: Option<usize>,
}
pub struct RandomPriorityAllocator {
num_resources: usize,
num_clients: usize,
requests: Vec<Request>,
rng: Option<StdRng>,
}
impl RandomPriorityAllocator {
pub fn new(args: AllocatorBuilderArgument) -> RandomPriorityAllocator {
if args.num_clients == 0 || args.num_resources == 0 {
panic!("Invalid arguments")
}
let mut seed = None;
match_object_panic!(args.cv, "RandomWithPriority", value,
"seed" => match value
{
&ConfigurationValue::Number(s) => seed = Some(s as u64),
_ => panic!("Bad value for seed"),
}
);
let rng = seed.map(|s| StdRng::seed_from_u64(s));
RandomPriorityAllocator {
num_resources: args.num_resources,
num_clients: args.num_clients,
requests: Vec::new(),
rng,
}
}
fn is_valid_request(&self, _request: &Request) -> bool {
if _request.client >= self.num_clients || _request.resource >= self.num_resources || _request.priority.is_none() {
return false
}
true
}
}
impl Allocator for RandomPriorityAllocator {
fn add_request(&mut self, request: Request) {
if !self.is_valid_request(&request) {
panic!("Invalid request");
}
self.requests.push(request);
}
fn perform_allocation(&mut self, rng : &mut StdRng) -> GrantedRequests {
let mut gr = GrantedRequests::default();
let mut resources: Vec<Resource> = vec![Resource::default(); self.num_resources];
let mut clients: Vec<Client> = vec![Client::default(); self.num_clients];
let rng = self.rng.as_mut().unwrap_or(rng);
self.requests.shuffle(rng);
self.requests.sort_by(|a, b| a.priority.unwrap().cmp(&b.priority.unwrap()));
for Request{ref resource, ref client, ref priority } in self.requests.iter() {
if resources[*resource].client.is_none() && clients[*client].resource.is_none() {
gr.add_granted_request(Request{
client: *client,
resource: *resource,
priority: *priority,
});
resources[*resource].client = Some(*client);
clients[*client].resource = Some(*resource);
} else {
continue;
}
}
self.requests.clear();
gr
}
fn support_intransit_priority(&self) -> bool {
true
}
}