pub struct AsyncTaskObject(/* private fields */);
Expand description
Handle to a Wolfram Language AsynchronousTaskObject
WL
instance.
Use spawn_with_thread()
to spawn a new
asynchronous task.
Implementations§
Source§impl AsyncTaskObject
impl AsyncTaskObject
Sourcepub fn spawn_with_thread<F>(f: F) -> Self
pub fn spawn_with_thread<F>(f: F) -> Self
Spawn a new Wolfram Language asynchronous task.
This method can be used within a LibraryLink function that was called via
Internal`CreateAsynchronousTask[
_LibraryFunction,
args_List,
handler
]
to create a new AsynchronousTaskObject
WL
that uses a background thread that can generate events that will be processed
asynchronously by the Wolfram Language.
The background thread is given an AsyncTaskObject
that has the same id as
the AsyncTaskObject
returned from this function. Events generated by the
background thread using raise_async_event()
will result in an asynchronous call to the Wolfram Language handler
function
specified in the call to Internal`CreateAsynchronousEvent
.
Examples found in repository?
13fn start_file_watcher(pause_interval_ms: mint, path: String) -> mint {
14 let pause_interval_ms =
15 u64::try_from(pause_interval_ms).expect("mint interval overflows u64");
16
17 let path = PathBuf::from(path);
18
19 // Spawn a new thread, which will run in the background and check for file
20 // modifications.
21 let task = AsyncTaskObject::spawn_with_thread(move |task: AsyncTaskObject| {
22 file_watch_thread_function(task, pause_interval_ms, &path);
23 });
24
25 task.id()
26}
Sourcepub fn id(&self) -> mint
pub fn id(&self) -> mint
Returns the numeric ID which identifies this async object.
Examples found in repository?
13fn start_file_watcher(pause_interval_ms: mint, path: String) -> mint {
14 let pause_interval_ms =
15 u64::try_from(pause_interval_ms).expect("mint interval overflows u64");
16
17 let path = PathBuf::from(path);
18
19 // Spawn a new thread, which will run in the background and check for file
20 // modifications.
21 let task = AsyncTaskObject::spawn_with_thread(move |task: AsyncTaskObject| {
22 file_watch_thread_function(task, pause_interval_ms, &path);
23 });
24
25 task.id()
26}
Sourcepub fn is_alive(&self) -> bool
pub fn is_alive(&self) -> bool
Returns whether this async task is still alive.
LibraryLink C Function: asynchronousTaskAliveQ
.
Examples found in repository?
29fn file_watch_thread_function(
30 task: AsyncTaskObject,
31 pause_interval_ms: u64,
32 path: &PathBuf,
33) {
34 let mut prev_changed: Option<SystemTime> = fs::metadata(path)
35 .and_then(|metadata| metadata.modified())
36 .ok();
37
38 // Stateful closure which checks if the file at `path` has been modified since the
39 // last time this closure was called (and `prev_changed was updated). Using a closure
40 // simplifies the control flow in the main `loop` below, which should sleep on every
41 // iteration regardless of how this function returns.
42 let mut check_for_modification = || -> Option<_> {
43 let changed: Option<fs::Metadata> = fs::metadata(path).ok();
44
45 let notify: Option<SystemTime> = match (&prev_changed, changed) {
46 (Some(prev), Some(latest)) => {
47 let latest: SystemTime = match latest.modified() {
48 Ok(latest) => latest,
49 Err(_) => return None,
50 };
51
52 if *prev != latest {
53 prev_changed = Some(latest.clone());
54 Some(latest)
55 } else {
56 None
57 }
58 },
59 // TODO: Notify on file removal?
60 (Some(_prev), None) => None,
61 (None, Some(latest)) => latest.modified().ok(),
62 (None, None) => None,
63 };
64
65 let time = notify?;
66
67 let since_epoch = match time.duration_since(std::time::UNIX_EPOCH) {
68 Ok(duration) => duration,
69 Err(_) => return None,
70 };
71
72 let since_epoch = since_epoch.as_secs();
73
74 Some(since_epoch)
75 };
76
77 loop {
78 if !task.is_alive() {
79 break;
80 }
81
82 // Check to see if the file has been modified. If it has, raise an async event
83 // called "change", and attach the modification timestamp as event data.
84 if let Some(modification) = check_for_modification() {
85 let mut data = DataStore::new();
86 data.add_i64(modification as i64);
87
88 task.raise_async_event("change", data);
89 }
90
91 // Wait for a bit before polling again for any changes to the file.
92 std::thread::sleep(Duration::from_millis(pause_interval_ms));
93 }
94}
Sourcepub fn is_started(&self) -> bool
pub fn is_started(&self) -> bool
Returns whether this async task has been started.
LibraryLink C Function: asynchronousTaskStartedQ
.
Sourcepub fn raise_async_event(&self, name: &str, data: DataStore)
pub fn raise_async_event(&self, name: &str, data: DataStore)
Raise a new named asynchronous event associated with the current async task.
§Example
Raise a new asynchronous event with no associated data:
This will cause the Wolfram Language event handler associated with this task to be run.
LibraryLink C Function: raiseAsyncEvent
.
use wolfram_library_link::{AsyncTaskObject, DataStore};
let task_object: AsyncTaskObject = todo!();
task_object.raise_async_event("change", DataStore::new());
Examples found in repository?
29fn file_watch_thread_function(
30 task: AsyncTaskObject,
31 pause_interval_ms: u64,
32 path: &PathBuf,
33) {
34 let mut prev_changed: Option<SystemTime> = fs::metadata(path)
35 .and_then(|metadata| metadata.modified())
36 .ok();
37
38 // Stateful closure which checks if the file at `path` has been modified since the
39 // last time this closure was called (and `prev_changed was updated). Using a closure
40 // simplifies the control flow in the main `loop` below, which should sleep on every
41 // iteration regardless of how this function returns.
42 let mut check_for_modification = || -> Option<_> {
43 let changed: Option<fs::Metadata> = fs::metadata(path).ok();
44
45 let notify: Option<SystemTime> = match (&prev_changed, changed) {
46 (Some(prev), Some(latest)) => {
47 let latest: SystemTime = match latest.modified() {
48 Ok(latest) => latest,
49 Err(_) => return None,
50 };
51
52 if *prev != latest {
53 prev_changed = Some(latest.clone());
54 Some(latest)
55 } else {
56 None
57 }
58 },
59 // TODO: Notify on file removal?
60 (Some(_prev), None) => None,
61 (None, Some(latest)) => latest.modified().ok(),
62 (None, None) => None,
63 };
64
65 let time = notify?;
66
67 let since_epoch = match time.duration_since(std::time::UNIX_EPOCH) {
68 Ok(duration) => duration,
69 Err(_) => return None,
70 };
71
72 let since_epoch = since_epoch.as_secs();
73
74 Some(since_epoch)
75 };
76
77 loop {
78 if !task.is_alive() {
79 break;
80 }
81
82 // Check to see if the file has been modified. If it has, raise an async event
83 // called "change", and attach the modification timestamp as event data.
84 if let Some(modification) = check_for_modification() {
85 let mut data = DataStore::new();
86 data.add_i64(modification as i64);
87
88 task.raise_async_event("change", data);
89 }
90
91 // Wait for a bit before polling again for any changes to the file.
92 std::thread::sleep(Duration::from_millis(pause_interval_ms));
93 }
94}