/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Machinery for [tasks](https://html.spec.whatwg.org/multipage/#concept-task).

use std::fmt;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

macro_rules! task {
    ($name:ident: |$($field:ident: $field_type:ty$(,)*)*| $body:tt) => {{
        #[allow(non_camel_case_types)]
        struct $name<F> {
            $($field: $field_type,)*
            task: F,
        }
        #[allow(unsafe_code)]
        unsafe impl<F> crate::JSTraceable for $name<F> {
            #[allow(unsafe_code)]
            unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
                $(self.$field.trace(tracer);)*
                // We cannot trace the actual task closure. This is safe because
                // all referenced values from within the closure are either borrowed
                // or moved into fields in the struct (and therefore traced).
            }
        }
        impl<F> crate::task::NonSendTaskOnce for $name<F>
        where
            F: ::std::ops::FnOnce($($field_type,)*),
        {
            fn run_once(self) {
                (self.task)($(self.$field,)*);
            }
        }
        $name {
            $($field,)*
            task: |$($field: $field_type,)*| $body,
        }
    }};

    ($name:ident: move || $body:tt) => {{
        #[allow(non_camel_case_types)]
        struct $name<F>(F);
        impl<F> crate::task::TaskOnce for $name<F>
        where
            F: ::std::ops::FnOnce() + Send,
        {
            fn name(&self) -> &'static str {
                stringify!($name)
            }

            fn run_once(self) {
                (self.0)();
            }
        }
        $name(move || $body)
    }};
}

/// A task that can be sent between threads and run.
/// The name method is for profiling purposes.
pub(crate) trait TaskOnce: Send {
    fn name(&self) -> &'static str {
        ::std::any::type_name::<Self>()
    }

    fn run_once(self);
}

/// A task that must be run on the same thread it originated in.
pub(crate) trait NonSendTaskOnce: crate::JSTraceable {
    fn run_once(self);
}

/// A boxed version of `TaskOnce`.
pub(crate) trait TaskBox: Send {
    fn name(&self) -> &'static str;

    fn run_box(self: Box<Self>);
}

/// A boxed version of `NonSendTaskOnce`.
pub(crate) trait NonSendTaskBox: crate::JSTraceable {
    fn run_box(self: Box<Self>);
}

impl<T> NonSendTaskBox for T
where
    T: NonSendTaskOnce,
{
    fn run_box(self: Box<Self>) {
        self.run_once()
    }
}

impl<T> TaskBox for T
where
    T: TaskOnce,
{
    fn name(&self) -> &'static str {
        TaskOnce::name(self)
    }

    fn run_box(self: Box<Self>) {
        self.run_once()
    }
}

impl fmt::Debug for dyn TaskBox {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple(self.name())
            .field(&format_args!("..."))
            .finish()
    }
}

/// Encapsulated state required to create cancellable tasks from non-script threads.
#[derive(Clone, Default, JSTraceable, MallocSizeOf)]
pub(crate) struct TaskCanceller {
    #[conditional_malloc_size_of]
    pub(crate) cancelled: Arc<AtomicBool>,
}

impl TaskCanceller {
    /// Returns a wrapped `task` that will be cancelled if the `TaskCanceller` says so.
    pub(crate) fn wrap_task<T>(&self, task: T) -> impl TaskOnce + use<T>
    where
        T: TaskOnce,
    {
        CancellableTask {
            canceller: self.clone(),
            inner: task,
        }
    }

    pub(crate) fn cancelled(&self) -> bool {
        self.cancelled.load(Ordering::SeqCst)
    }
}

/// A task that can be cancelled by toggling a shared flag.
pub(crate) struct CancellableTask<T: TaskOnce> {
    canceller: TaskCanceller,
    inner: T,
}

impl<T: TaskOnce> TaskOnce for CancellableTask<T> {
    fn name(&self) -> &'static str {
        self.inner.name()
    }

    fn run_once(self) {
        if !self.canceller.cancelled() {
            self.inner.run_once()
        }
    }
}
