tasks-framework 0.1.0

Actor-like Message processing framework inspired by the work of Stepan Koltsov.
Documentation
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier};
use std::marker::Sync;
use threadpool::ThreadPool;

use tasks::Tasks;
use runnable::Runnable;

pub struct ActorRunner<T: Runnable + Send + Sync + 'static> {
    tasks: Arc<Tasks>,
    shutdown: Arc<AtomicBool>,
    complete_status: Arc<Barrier>,

    actor: Arc<T>,
    execution_pool: Arc<ThreadPool>
}

impl<T: Runnable + Send + Sync + 'static> ActorRunner<T> {
    pub fn new( actor: T, execution_pool: Arc<ThreadPool> ) -> ActorRunner<T> {
        ActorRunner {
            tasks: Arc::new(Tasks::new()),
            shutdown: Arc::new(AtomicBool::new(false)),
            complete_status: Arc::new(Barrier::new(2)),

            actor: Arc::new(actor),
            execution_pool: execution_pool
        }
    }

    pub fn schedule(&self) {
        if self.tasks.add_task() {
            let tasks_ref = self.tasks.clone();
            let actor_ref = self.actor.clone();
            let shutdown_ref = self.shutdown.clone();
            let complete_status_ref = self.complete_status.clone();

            self.execution_pool.execute(move || {
                while tasks_ref.fetch_task() {
                    actor_ref.run();

                    if shutdown_ref.load(Ordering::Relaxed) {
                        complete_status_ref.wait();
                    }
                }
            })
        }
    }

    pub fn complete(&self) {
        self.shutdown.store(true, Ordering::Relaxed);
        self.schedule();

        self.complete_status.wait();
    }
}

impl<T: Runnable + Send + Sync + 'static> Drop for ActorRunner<T> {
    fn drop(&mut self) {
        self.complete();
    }
}