wild_thread_pool 0.4.0

wild thread pool
Documentation
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate closer;
extern crate wild_thread_pool;

use std::thread;
use std::time::Duration;
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{self, Display};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use wild_thread_pool::{ThreadPool, NewWorker, Worker, DefaultShutdown, ErrorExt};

// RUST_LOG=debug cargo run --example hello
fn main() {
    env_logger::init().unwrap();

    let closer = closer::Closer::init();

    let thread_pool = ThreadPool::new(
        2,
        Duration::from_secs(2),
        Duration::from_secs(2),
        closer.closed(),
    );
    let new_hello_worker = NewHelloWorker::new();
    let workes = thread_pool.run(new_hello_worker);

    workes.wait().unwrap();
}

struct NewHelloWorker {
    global_counter: Arc<AtomicUsize>,
}

impl NewHelloWorker {
    fn new() -> NewHelloWorker {
        NewHelloWorker { global_counter: Arc::new(AtomicUsize::new(0)) }
    }
}

impl NewWorker for NewHelloWorker {
    type Worker = HelloWorker;

    fn new_worker(&self, worker_id: u64) -> Self::Worker {
        HelloWorker::new(worker_id, self.global_counter.clone())
    }
}

#[derive(Debug)]
struct Err(Cow<'static, str>);

impl Error for Err {
    fn description(&self) -> &str {
        self.0.as_ref()
    }
}

impl Display for Err {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl ErrorExt for Err {
    fn new_err(s: Cow<'static, str>) -> Self {
        Err(s)
    }
}

#[derive(Clone)]
struct HelloWorker {
    worker_id: u64,
    global_counter: Arc<AtomicUsize>,
    worker_counter: Arc<AtomicUsize>,
}

impl HelloWorker {
    fn new(worker_id: u64, global_counter: Arc<AtomicUsize>) -> HelloWorker {
        let worker_counter = Arc::new(AtomicUsize::new(0));

        HelloWorker {
            worker_id,
            global_counter,
            worker_counter,
        }
    }
}

impl Worker for HelloWorker {
    type Shutdown = DefaultShutdown;
    type Err = Err;

    fn worker_id(&self) -> u64 {
        self.worker_id
    }

    fn on_tick(&self) -> Result<(), Err> {
        self.global_counter.fetch_add(1, Ordering::Relaxed);
        self.worker_counter.fetch_add(1, Ordering::Relaxed);

        let global_counter = self.global_counter.load(Ordering::Relaxed);
        let worker_counter = self.worker_counter.load(Ordering::Relaxed);
        info!(
            "worker-{}, tick, global_counter = {}, worker_counter = {}",
            self.worker_id,
            global_counter,
            worker_counter
        );

        // if worker_counter % 4 == 0 {
        //     panic!("2");
        // }

        thread::sleep(Duration::from_secs(2));

        Ok(())
    }

    fn new_shutdown(&self) -> Self::Shutdown {
        DefaultShutdown::new(self.worker_id)
    }
}