pub fn new(thread_name: &str, num_threads: usize) -> Self {
        let thread_name = thread_name.to_string();

        let (tx_tasks, rx_tasks) = std::sync::mpsc::channel::<Task>();
        let (tx_shutdown, rx_shutdown) = tokio::sync::oneshot::channel();

        let thread = std::thread::spawn(move || {
            let runtime = tokio::runtime::Builder::new_multi_thread()
                .enable_all()
                .thread_name(&thread_name)
                .worker_threads(num_threads)
                .on_thread_start(move || set_current_thread_priority(WORKER_PRIORITY))
                .build()
                .expect("Creating tokio runtime");

            runtime.block_on(async move {
                // Dropping the tokio runtime only waits for tasks to yield not to complete
                //
                // We therefore use a RwLock to wait for tasks to complete
                let join = Arc::new(tokio::sync::RwLock::new(()));

                while let Ok(task) = rx_tasks.recv() {
                    let join = Arc::clone(&join);
                    let handle = join.read_owned().await;

                    tokio::task::spawn(async move {
                        task.run().await;
                        std::mem::drop(handle);
                    });
                }

                // Wait for all tasks to finish
                join.write().await;

                // signal shutdown, but it's OK if the other side is gone
                tx_shutdown.send(()).ok();
            })
        });

        let state = State {
            requests: Some(tx_tasks),
            task_refs: Arc::new(()),
            completed_shutdown: rx_shutdown.map_err(Arc::new).boxed().shared(),
            thread: Some(thread),
        };

        Self {
            state: Arc::new(Mutex::new(state)),
        }
    }
/// Creates a new `DedicatedExecutor` with a dedicated tokio
/// executor that is separate from the threadpool created via
/// `[tokio::main]` or similar.
///
/// The worker thread priority is set to low so that such tasks do
/// not starve other more important tasks (such as answering health checks)
///
/// Follows the example from to stack overflow and spawns a new
/// thread to install a Tokio runtime "context"
/// <https://stackoverflow.com/questions/62536566>
///
/// If you try to do this from a async context you see something like
/// thread 'plan::stringset::tests::test_builder_plan' panicked at 'Cannot
/// drop a runtime in a context where blocking is not allowed. This
/// happens when a runtime is dropped from within an asynchronous
/// context.', .../tokio-1.4.0/src/runtime/blocking/shutdown.rs:51:21
Creates a new `DedicatedExecutor` with a dedicated tokio
executor that is separate from the threadpool created via
`[tokio::main]` or similar.

The worker thread priority is set to low so that such tasks do
not starve other more important tasks (such as answering health checks)

Follows the example from to stack overflow and spawns a new
thread to install a Tokio runtime "context"


Creates a new ` DedicatedExecutor ` with a dedicated tokio executor that is separate from the threadpool created via ` [ tokio :: main ] ` or similar . The worker thread priority is set to low so that such tasks do not starve other more important tasks ( such as answering health checks ) Follows the example from to stack overflow and spawns a new thread to install a Tokio runtime " context "
pub fn new(thread_name: &str, num_threads: usize) -> Self {
        let thread_name = thread_name.to_string();
        let (tx_tasks, rx_tasks) = std::sync::mpsc::channel::<Task>();
        let (tx_shutdown, rx_shutdown) = tokio::sync::oneshot::channel();
        let thread = std::thread::spawn(move || {
            let runtime = tokio::runtime::Builder::new_multi_thread()
                .enable_all()
                .thread_name(&thread_name)
                .worker_threads(num_threads)
                .on_thread_start(move || set_current_thread_priority(WORKER_PRIORITY))
                .build()
                .expect("Creating tokio runtime");
            runtime.block_on(async move {
                // Dropping the tokio runtime only waits for tasks to yield not to complete
                //
                // We therefore use a RwLock to wait for tasks to complete
                let join = Arc::new(tokio::sync::RwLock::new(()));
                while let Ok(task) = rx_tasks.recv() {
                    let join = Arc::clone(&join);
                    let handle = join.read_owned().await;
                    tokio::task::spawn(async move {
                        task.run().await;
                        std::mem::drop(handle);
                    });
                }
                // Wait for all tasks to finish
                join.write().await;
                // signal shutdown, but it's OK if the other side is gone
                tx_shutdown.send(()).ok();
            })
        });
        let state = State {
            requests: Some(tx_tasks),
            task_refs: Arc::new(()),
            completed_shutdown: rx_shutdown.map_err(Arc::new).boxed().shared(),
            thread: Some(thread),
        };
        Self {
            state: Arc::new(Mutex::new(state)),
        }
    }
pub fn new ( thread_name : & str , num_threads : usize ) -> Self { let thread_name = thread_name . to_string ( ) ; let ( tx_tasks , rx_tasks ) = std :: sync :: mpsc :: channel :: < Task > ( ) ; let ( tx_shutdown , rx_shutdown ) = tokio :: sync :: oneshot :: channel ( ) ; let thread = std :: thread :: spawn ( move | | { let runtime = tokio :: runtime :: Builder :: new_multi_thread ( ) . enable_all ( ) . thread_name ( & thread_name ) . worker_threads ( num_threads ) . on_thread_start ( move | | set_current_thread_priority ( WORKER_PRIORITY ) ) . build ( ) . expect ( " " ) ; runtime . block_on ( async move { // Dropping the tokio runtime only waits for tasks to yield not to complete // // We therefore use a RwLock to wait for tasks to complete let join = Arc :: new ( tokio :: sync :: RwLock :: new ( ( ) ) ) ; while let Ok ( task ) = rx_tasks . recv ( ) { let join = Arc :: clone ( & join ) ; let handle = join . read_owned ( ) . await ; tokio :: task :: spawn ( async move { task . run ( ) . await ; std :: mem :: drop ( handle ) ; } ) ; } // Wait for all tasks to finish join . write ( ) . await ; // signal shutdown, but it's OK if the other side is gone tx_shutdown . send ( ( ) ) . ok ( ) ; } ) } ) ; let state = State { requests : Some ( tx_tasks ) , task_refs : Arc :: new ( ( ) ) , completed_shutdown : rx_shutdown . map_err ( Arc :: new ) . boxed ( ) . shared ( ) , thread : Some ( thread ) , } ; Self { state : Arc :: new ( Mutex :: new ( state ) ) , } }
Creates a new `DedicatedExecutor` with a dedicated tokio
executor that is separate from the threadpool created via
`[tokio::main]` or similar.
Creates a new ` DedicatedExecutor ` with a dedicated tokio executor that is separate from the threadpool created via ` [ tokio :: main ] ` or similar .
thread_name
&str
num_threads
usize
thread_name
&str
num_threads
usize