yew_agent/worker/
lifecycle.rs1use wasm_bindgen::prelude::*;
2
3use super::messages::ToWorker;
4use super::native_worker::{DedicatedWorker, WorkerSelf};
5use super::scope::{WorkerDestroyHandle, WorkerScope};
6use super::traits::Worker;
7use super::Shared;
8
9pub(crate) struct WorkerState<W>
10where
11 W: Worker,
12{
13 worker: Option<(W, WorkerScope<W>)>,
14 to_destroy: bool,
15}
16
17impl<W> WorkerState<W>
18where
19 W: Worker,
20{
21 pub fn new() -> Self {
22 WorkerState {
23 worker: None,
24 to_destroy: false,
25 }
26 }
27}
28
29pub(crate) enum WorkerLifecycleEvent<W: Worker> {
31 Create(WorkerScope<W>),
33
34 Message(W::Message),
36
37 Remote(ToWorker<W>),
39
40 Destroy,
42}
43
44pub(crate) struct WorkerRunnable<W: Worker> {
45 pub state: Shared<WorkerState<W>>,
46 pub event: WorkerLifecycleEvent<W>,
47}
48
49impl<W> WorkerRunnable<W>
50where
51 W: Worker + 'static,
52{
53 pub fn run(self) {
54 let mut state = self.state.borrow_mut();
55
56 match self.event {
58 WorkerLifecycleEvent::Create(scope) => {
59 if state.to_destroy {
60 return;
61 }
62 state.worker = Some((W::create(&scope), scope));
63 }
64 WorkerLifecycleEvent::Message(msg) => {
65 if let Some((worker, scope)) = state.worker.as_mut() {
66 worker.update(scope, msg);
67 }
68 }
69 WorkerLifecycleEvent::Remote(ToWorker::Connected(id)) => {
70 if state.to_destroy {
71 return;
72 }
73
74 let (worker, scope) = state
75 .worker
76 .as_mut()
77 .expect_throw("worker was not created to process connected messages");
78
79 worker.connected(scope, id);
80 }
81 WorkerLifecycleEvent::Remote(ToWorker::ProcessInput(id, inp)) => {
82 if state.to_destroy {
83 return;
84 }
85
86 let (worker, scope) = state
87 .worker
88 .as_mut()
89 .expect_throw("worker was not created to process inputs");
90
91 worker.received(scope, inp, id);
92 }
93 WorkerLifecycleEvent::Remote(ToWorker::Disconnected(id)) => {
94 if state.to_destroy {
95 return;
96 }
97
98 let (worker, scope) = state
99 .worker
100 .as_mut()
101 .expect_throw("worker was not created to process disconnected messages");
102
103 worker.disconnected(scope, id);
104 }
105 WorkerLifecycleEvent::Remote(ToWorker::Destroy) => {
106 if state.to_destroy {
107 return;
108 }
109
110 state.to_destroy = true;
111
112 let (worker, scope) = state
113 .worker
114 .as_mut()
115 .expect_throw("trying to destroy not existent worker");
116
117 let destruct = WorkerDestroyHandle::new(scope.clone());
118
119 worker.destroy(scope, destruct);
120 }
121
122 WorkerLifecycleEvent::Destroy => {
123 state
124 .worker
125 .take()
126 .expect_throw("worker is not initialised or already destroyed");
127
128 DedicatedWorker::worker_self().close();
129 }
130 }
131 }
132}