1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
use std::cell::RefCell;
use std::mem;
use std::ops::Deref;
use std::ptr::NonNull;
use std::sync::{Arc, Mutex, MutexGuard, Weak};

/// Internal trait
trait Functor: Sync + Send {
    /// Call binded function.
    fn call(&self);
}

/// Task type that stores lambda function closure.
struct TaskClosure<F> {
    f: F,
}

impl<F> Functor for TaskClosure<F>
where
    F: Fn() + Sync + Send,
{
    /// Call inside closure.
    fn call(&self) {
        (self.f)()
    }
}

unsafe impl<F> Sync for TaskClosure<F> where F: Fn() + Sync + Send {}
unsafe impl<F> Send for TaskClosure<F> where F: Fn() + Sync + Send {}

/// Task type that stores valid item's pointer and valid method reference of item.
///
/// This only can store `&T` const method, use `TaskMethodMut` if using mutable method of `&mut T`.
/// Binded item's pointer should not be invalidated, or moved.
/// Calling moved item's method may be occur undefined behavior by following additional logics.
struct TaskMethod<T, F> {
    t: NonNull<T>,
    f: F,
}

impl<T, F> Functor for TaskMethod<T, F>
where
    F: Fn(&T) + Sync + Send,
{
    // Call const method.
    fn call(&self) {
        (self.f)(unsafe { self.t.as_ref() })
    }
}

unsafe impl<T, F> Sync for TaskMethod<T, F> where F: Fn(&T) + Sync + Send {}
unsafe impl<T, F> Send for TaskMethod<T, F> where F: Fn(&T) + Sync + Send {}

/// Task type that stores valid item's pointer and valid muable method reference of item.
///
/// This only can store `&mut T` mutable method, use `TaskMethod` if want to use immutable method of `&T`.
/// Binded item's pointer should not be invalidated, or moved.
/// Calling moved item's method may be occur undefined behavior by following additional logics.
struct TaskMethodMut<T, F> {
    t: RefCell<NonNull<T>>,
    f: F,
}

impl<T, F> Functor for TaskMethodMut<T, F>
where
    F: Fn(&mut T) + Sync + Send,
{
    // Call mutable method.
    fn call(&self) {
        (self.f)(unsafe { self.t.borrow_mut().as_mut() })
    }
}

unsafe impl<T, F> Sync for TaskMethodMut<T, F> where F: Fn(&mut T) + Sync + Send {}
unsafe impl<T, F> Send for TaskMethodMut<T, F> where F: Fn(&mut T) + Sync + Send {}

/// Raw type for `Task` instance.
///
/// Stores actual informations for task.
pub struct TaskRaw {
    pub name: String,
    func: Option<Box<dyn Functor>>,
}

impl TaskRaw {
    /// Call binded function (closure, or methods).
    pub(crate) fn call(&self) {
        if let Some(func) = &self.func {
            func.call();
        }
    }

    /// Create intentional empty task which does nothing.
    fn empty_task() -> Self {
        Self {
            name: "_".into(),
            func: None,
        }
    }

    /// Create task which is binding lambda closure.
    ///
    /// Given name must be valid and not empty. It's ok to be duplicated with other task's name.
    fn from_closure<F>(name: &str, f: F) -> Self
    where
        F: Fn() + Sync + Send + 'static,
    {
        assert!(name.is_empty() == false, "Task name must not be empty.");
        Self {
            name: name.to_string(),
            func: Some(Box::new(TaskClosure { f })),
        }
    }

    /// Create task which is binding item's pointer and valid immutable method from the item.
    ///
    /// Given name must be valid and not empty. It's ok to be duplicated with other task's name.
    /// Being binded item should not be invalidated, or moved state.
    /// Otherwise, calling invalidated item's method will be undefined behavior.
    ///
    /// Calling method of task may not invalidate borrowing rule, but care about synchronization
    /// and data race manually in the logic.
    fn from_method<T, F>(name: &'_ str, t: &T, f: F) -> Self
    where
        T: 'static,
        F: Fn(&T) + Sync + Send + 'static,
    {
        assert!(name.is_empty() == false, "Task name must not be empty.");
        let t = NonNull::new(t as *const _ as *mut T).unwrap();

        Self {
            name: name.to_string(),
            func: Some(Box::new(TaskMethod { t, f })),
        }
    }

    /// Create task which is binding item's pointer and valid mutable method from the item.
    ///
    /// Given name must be valid and not empty. It's ok to be duplicated with other task's name.
    /// Being binded item should not be invalidated, or moved state.
    /// Otherwise, calling invalidated item's immutable method will be undefined behavior.
    ///
    /// Calling method of task may not invalidate borrowing rule, but care about synchronization
    /// and data race manually in the logic.
    fn from_method_mut<T, F>(name: &'_ str, t: &mut T, f: F) -> Self
    where
        T: 'static,
        F: Fn(&mut T) + Sync + Send + 'static,
    {
        let t = RefCell::new(NonNull::new(t as *mut T).unwrap());

        Self {
            name: name.to_string(),
            func: Some(Box::new(TaskMethodMut { t, f })),
        }
    }
}

/// Task instance which callable in any thread context in the system.
pub struct Task {
    raw: Arc<Mutex<TaskRaw>>,
}

impl Task {
    /// Get the name of the task.
    pub fn name(&self) -> String {
        self.raw.lock().unwrap().name.clone()
    }

    /// Get new handle of the task.
    pub fn handle(&self) -> TaskHandle {
        TaskHandle {
            value: Arc::downgrade(&self.raw),
        }
    }

    /// Create intentional empty task which does nothing.
    pub(crate) fn empty_task() -> Self {
        let raw = TaskRaw::empty_task();
        Self {
            raw: Arc::new(Mutex::new(raw)),
        }
    }

    /// Create task which is binding lambda closure.
    ///
    /// Given name must be valid and not empty. It's ok to be duplicated with other task's name.
    pub(crate) fn from_closure<F>(name: &str, f: F) -> Self
    where
        F: Fn() + Sync + Send + 'static,
    {
        let raw = TaskRaw::from_closure(name, f);
        Self {
            raw: Arc::new(Mutex::new(raw)),
        }
    }

    /// Create task which is binding item's pointer and valid immutable method from the item.
    ///
    /// Given name must be valid and not empty. It's ok to be duplicated with other task's name.
    /// Being binded item should not be invalidated, or moved state.
    /// Otherwise, calling invalidated item's method will be undefined behavior.
    ///
    /// Calling method of task may not invalidate borrowing rule, but care about synchronization
    /// and data race manually in the logic.
    pub(crate) fn from_method<T, F>(name: &'_ str, t: &T, f: F) -> Self
    where
        T: 'static,
        F: Fn(&T) + Sync + Send + 'static,
    {
        let raw = TaskRaw::from_method(name, t, f);
        Self {
            raw: Arc::new(Mutex::new(raw)),
        }
    }

    /// Create task which is binding item's pointer and valid mutable method from the item.
    ///
    /// Given name must be valid and not empty. It's ok to be duplicated with other task's name.
    /// Being binded item should not be invalidated, or moved state.
    /// Otherwise, calling invalidated item's immutable method will be undefined behavior.
    ///
    /// Calling method of task may not invalidate borrowing rule, but care about synchronization
    /// and data race manually in the logic.
    pub(crate) fn from_method_mut<T, F>(name: &'_ str, t: &mut T, f: F) -> Self
    where
        T: 'static,
        F: Fn(&mut T) + Sync + Send + 'static,
    {
        let raw = TaskRaw::from_method_mut(name, t, f);
        Self {
            raw: Arc::new(Mutex::new(raw)),
        }
    }

    /// Call task's function.
    ///
    /// # Notes
    ///
    /// Maybe performance down by locking whenever calling callbacks.
    pub(crate) fn call(&self) {
        self.raw.lock().unwrap().call();
    }
}

/// Handle type for the task in arbitrary group.
#[derive(Clone)]
pub struct TaskHandle {
    value: Weak<Mutex<TaskRaw>>,
}

impl TaskHandle {
    /// Access to the task execusively and return accessor `TaskAccssor` item.
    ///
    /// If actual task item is invalidated, do nothing just return `None` value.
    pub fn value_as_ref<'a>(&'a self) -> Option<TaskAccessor<'a>> {
        let task = self.value.upgrade()?;
        let task_lock = task.lock();
        if let Ok(task_guard) = task_lock {
            // Warning!
            let task_guard: MutexGuard<'a, TaskRaw> = unsafe { mem::transmute(task_guard) };
            Some(TaskAccessor { task_guard })
        } else {
            None
        }
    }

    /// Check task is released or not.
    pub fn is_released(&self) -> bool {
        self.value.strong_count() == 0
    }
}

/// Accessor item type for task.
pub struct TaskAccessor<'a> {
    task_guard: MutexGuard<'a, TaskRaw>,
}

impl<'a> Deref for TaskAccessor<'a> {
    type Target = TaskRaw;

    fn deref(&self) -> &Self::Target {
        self.task_guard.deref()
    }
}