urls2disk 0.1.1

Http client to download urls to disk concurrently, optionally converting them to PDF
Documentation
use std::sync::{Condvar, Mutex};

use num_cpus;

#[derive(Debug)]
pub(crate) struct Semaphore {
    max_requests_per_second: usize,
    max_threads_cpu: usize,
    max_threads_io: usize,

    requests: Mutex<usize>,
    requests_condvar: Condvar,
    threads_cpu: Mutex<usize>,
    threads_cpu_condvar: Condvar,
    threads_io: Mutex<usize>,
    threads_io_condvar: Condvar,
}

impl Default for Semaphore {
    fn default() -> Self {
        Semaphore {
            max_requests_per_second: 10,
            max_threads_cpu: num_cpus::get(),
            max_threads_io: 100,

            requests: Mutex::new(0),
            requests_condvar: Condvar::new(),
            threads_cpu: Mutex::new(0),
            threads_cpu_condvar: Condvar::new(),
            threads_io: Mutex::new(0),
            threads_io_condvar: Condvar::new(),
        }
    }
}

impl Semaphore {
    pub(crate) fn new(
        max_requests_per_second: usize,
        max_threads_cpu: usize,
        max_threads_io: usize,
    ) -> Self {
        let mut semaphore = Self::default();
        semaphore.max_requests_per_second = max_requests_per_second;
        semaphore.max_threads_cpu = max_threads_cpu;
        semaphore.max_threads_io = max_threads_io;
        semaphore
    }
    pub(crate) fn reset_requests(&self) {
        let mut requests = self.requests.lock().unwrap();
        *requests = 0;
        self.requests_condvar.notify_one();
    }
    pub(crate) fn increment_requests(&self) {
        let mut requests = self.requests.lock().unwrap();
        while *requests >= self.max_requests_per_second {
            requests = self.requests_condvar.wait(requests).unwrap()
        }
        *requests += 1;
        self.requests_condvar.notify_one();
    }
    pub(crate) fn increment_threads_cpu(&self) {
        let mut threads_cpu = self.threads_cpu.lock().unwrap();
        while *threads_cpu >= self.max_threads_cpu {
            threads_cpu = self.threads_cpu_condvar.wait(threads_cpu).unwrap()
        }
        *threads_cpu += 1;
        self.threads_cpu_condvar.notify_one();
    }
    pub(crate) fn decrement_threads_cpu(&self) {
        let mut threads_cpu = self.threads_cpu.lock().unwrap();
        *threads_cpu -= 1;
        self.threads_cpu_condvar.notify_one();
    }
    pub(crate) fn increment_threads_io(&self) {
        let mut threads_io = self.threads_io.lock().unwrap();
        while *threads_io >= self.max_threads_io {
            threads_io = self.threads_io_condvar.wait(threads_io).unwrap()
        }
        *threads_io += 1;
        self.threads_io_condvar.notify_one();
    }
    pub(crate) fn decrement_threads_io(&self) {
        let mut threads_io = self.threads_io.lock().unwrap();
        *threads_io -= 1;
        self.threads_io_condvar.notify_one();
    }
}