fromsoftware_shared/
task.rs1use std::{
2 cell::UnsafeCell,
3 ffi::c_void,
4 sync::{
5 Arc,
6 atomic::{AtomicBool, Ordering},
7 },
8};
9
10use vtable_rs::VPtr;
11
12pub trait SharedTaskImp<TIndex, TTaskData: Send + 'static> {
14 fn register_task_internal(&self, index: TIndex, task: &RecurringTask<TTaskData>);
17}
18
19pub trait SharedTaskImpExt<TIndex, TTaskData: Send + 'static> {
22 fn run_recurring<T: Into<RecurringTask<TTaskData>>>(
24 &self,
25 execute: T,
26 group: TIndex,
27 ) -> RecurringTaskHandle<TTaskData>;
28}
29
30impl<TIndex, TTaskData: Send + 'static, S: SharedTaskImp<TIndex, TTaskData>>
31 SharedTaskImpExt<TIndex, TTaskData> for S
32{
33 fn run_recurring<T: Into<RecurringTask<TTaskData>>>(
34 &self,
35 task: T,
36 group: TIndex,
37 ) -> RecurringTaskHandle<TTaskData> {
38 #[allow(clippy::arc_with_non_send_sync)]
39 let task: Arc<RecurringTask<TTaskData>> = Arc::new(task.into());
40 unsafe {
42 *task.self_ref.get() = Some(task.clone());
43 }
44
45 self.register_task_internal(group, task.as_ref());
46
47 RecurringTaskHandle { _task: task }
48 }
49}
50
51pub struct RecurringTaskHandle<TTaskData: Send + 'static> {
54 _task: Arc<RecurringTask<TTaskData>>,
55}
56
57impl<TTaskData: Send + 'static> Drop for RecurringTaskHandle<TTaskData> {
58 fn drop(&mut self) {
59 self._task.cancel();
60 }
61}
62
63#[repr(C)]
70pub struct RecurringTask<TTaskData: Send + 'static> {
71 vftable: VPtr<dyn SharedTaskBaseVmt, Self>,
72 unk8: usize,
73 closure: Box<dyn FnMut(&TTaskData)>,
74 unregister_requested: AtomicBool,
75 self_ref: UnsafeCell<Option<Arc<Self>>>,
76}
77
78impl<TTaskData: Send + 'static> RecurringTask<TTaskData> {
79 pub fn new<F: FnMut(&TTaskData) + 'static + Send>(closure: F) -> Self {
80 Self {
81 vftable: Default::default(),
82 unk8: 0,
83 closure: Box::new(closure),
84 unregister_requested: AtomicBool::new(false),
85 self_ref: UnsafeCell::new(None),
86 }
87 }
88
89 pub fn cancel(&self) {
90 self.unregister_requested.store(true, Ordering::Relaxed);
91 }
92}
93
94impl<TTaskData: Send + 'static> SharedTaskBaseVmt for RecurringTask<TTaskData> {
95 extern "C" fn get_runtime_class(&self) -> usize {
96 unimplemented!();
97 }
98
99 extern "C" fn destructor(&mut self) {
100 unimplemented!();
101 }
102
103 extern "C" fn execute(&mut self, data: *const c_void) {
104 (self.closure)(unsafe { &*(data as *const TTaskData) });
109
110 }
120}
121
122impl<TTaskData: Send + 'static, F: FnMut(&TTaskData) + 'static + Send> From<F>
123 for RecurringTask<TTaskData>
124{
125 fn from(value: F) -> Self {
126 Self::new(value)
127 }
128}
129
130#[vtable_rs::vtable]
131trait SharedTaskBaseVmt {
132 fn get_runtime_class(&self) -> usize;
133
134 fn destructor(&mut self);
135
136 fn execute(&mut self, data: *const c_void);
138}