Skip to content

Commit

Permalink
Add multithreading example (#2171)
Browse files Browse the repository at this point in the history
* correctly reflect the status of multi_thread example

* commiting a partially working example ported from 0.18 to next

* make the app actually start

* remove example from github workflows

* rust-fmt

* cargo make pr-flow done succesfully :)

* update per comments

* fix build errors

* fix cargo fmt

* fix stuff

* Apply suggestions from code review

Co-authored-by: mc1098 <m.cripps1@uni.brighton.ac.uk>

* Update examples/web_worker_fib/src/app.rs

Co-authored-by: mc1098 <m.cripps1@uni.brighton.ac.uk>

* Remove space

* Update .github/workflows/publish-examples.yml

Co-authored-by: WorldSEnder <WorldSEnder@users.noreply.github.com>

Co-authored-by: SpanishPear <shrey.somaiya@gmail.com>
Co-authored-by: mc1098 <m.cripps1@uni.brighton.ac.uk>
Co-authored-by: WorldSEnder <WorldSEnder@users.noreply.github.com>
  • Loading branch information
4 people committed Nov 23, 2021
1 parent 8d674c5 commit c0f584c
Show file tree
Hide file tree
Showing 11 changed files with 232 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .github/workflows/publish-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ jobs:
continue
fi
# web_worker_fib does not compile with trunk. See <https://github.com/thedodd/trunk/issues/46>.
if [[ "$example" == "web_worker_fib" ]]; then
continue
fi
echo "building: $example"
(
cd "$path"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ members = [
"examples/todomvc",
"examples/two_apps",
"examples/webgl",
"examples/web_worker_fib",

# Release tools
"packages/changelog",
Expand Down
8 changes: 7 additions & 1 deletion examples/multi_thread/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Warning

The multi-thread example is a conceptual WIP and is currently blocked on [a future Trunk feature](https://github.com/thedodd/trunk/issues/46)

There is an alternate multi-thread example [here](https://github.com/yewstack/yew/tree/master/examples/web_worker_fib).


# Multi-Thread Example

[![Demo](https://img.shields.io/website?label=demo&url=https%3A%2F%2Fexamples.yew.rs%2Fmulti_thread)](https://examples.yew.rs/multi_thread)

**WIP**: [thedodd/trunk#46](https://github.com/thedodd/trunk/issues/46)

## Concepts

Expand Down
16 changes: 16 additions & 0 deletions examples/web_worker_fib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "yew-worker-fib"
version = "0.1.0"
edition = "2018"
author = "Shrey Somaiya"

[lib]
crate-type = ["cdylib"]

[dependencies]
yew = { path = "../../packages/yew" }
yew-agent = { path = "../../packages/yew-agent" }
wasm-bindgen = "0.2"
js-sys = "0.3"
web-sys = { version = "0.3", features = [ "HtmlInputElement" ] }
serde = "1"
27 changes: 27 additions & 0 deletions examples/web_worker_fib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Web Worker Demo

Calculate fibbonnaci value of a number in the worker thread,
without blocking the main thread.

You can access a live version here:

# Running this example

do `./build.sh && ./serve.sh`

## notes

This example is NOT built with [trunk](https://github.com/thedodd/trunk).
Multi-threading in yew does not currently build with Trunk, due to issues described in the [multi_thread](/examples/multi_thread/README.md) example.

Instead the example is built with [`wasm-pack`](https://rustwasm.github.io/wasm-pack/) directly.

To build, run `./build.sh`.
You can then serve the build, with `./serve.sh`.

This example uses python3 as a server, any alternative will work.

# Thanks to

- [insou22](https://github.com/insou22) for writing up the demo.
- [https://github.com/yvt/img2text](https://github.com/yvt/img2text) -- for how to make web workers compile in wasm
8 changes: 8 additions & 0 deletions examples/web_worker_fib/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
if ! command -v wasm-pack 2>&1 >/dev/null;
then
echo 'error: you must install wasm-pack'
exit
fi

wasm-pack build --target no-modules --out-name wasm --out-dir ./static --no-typescript
9 changes: 9 additions & 0 deletions examples/web_worker_fib/serve.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
if ! command -v python3 2>&1 >/dev/null;
then
echo 'error: you must install python3'
exit
fi

cd static/
python3 -m http.server 8080
55 changes: 55 additions & 0 deletions examples/web_worker_fib/src/agent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use serde::{Deserialize, Serialize};
use yew_agent::{Agent, AgentLink, HandlerId, Public};

pub struct Worker {
link: AgentLink<Self>,
}

#[derive(Serialize, Deserialize)]
pub struct WorkerInput {
pub n: u32,
}

#[derive(Serialize, Deserialize)]
pub struct WorkerOutput {
pub value: u32,
}

impl Agent for Worker {
type Reach = Public<Self>;
type Message = ();
type Input = WorkerInput;
type Output = WorkerOutput;

fn create(link: AgentLink<Self>) -> Self {
Self { link }
}

fn update(&mut self, _msg: Self::Message) {
// no messaging
}

fn handle_input(&mut self, msg: Self::Input, id: HandlerId) {
// this runs in a web worker
// and does not block the main
// browser thread!

let n = msg.n;

fn fib(n: u32) -> u32 {
if n <= 1 {
1
} else {
fib(n - 1) + fib(n - 2)
}
}

let output = Self::Output { value: fib(n) };

self.link.respond(id, output);
}

fn name_of_resource() -> &'static str {
"wasm.js"
}
}
73 changes: 73 additions & 0 deletions examples/web_worker_fib/src/app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::agent::{Worker, WorkerInput, WorkerOutput};

use web_sys::HtmlInputElement;
use yew::prelude::*;
use yew_agent::{Bridge, Bridged};

pub struct Model {
clicker_value: u32,
input_ref: NodeRef,
worker: Box<dyn Bridge<Worker>>,
fibonacci_output: String,
}

pub enum Message {
Click,
RunWorker,
WorkerMsg(WorkerOutput),
}

impl Component for Model {
type Message = Message;
type Properties = ();

fn create(ctx: &Context<Self>) -> Self {
let worker = Worker::bridge(ctx.link().callback(Self::Message::WorkerMsg));

Self {
clicker_value: 0,
input_ref: NodeRef::default(),
worker,
fibonacci_output: String::from("Try out some fibonacci calculations!"),
}
}

fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Self::Message::Click => {
self.clicker_value += 1;
}
Self::Message::RunWorker => {
if let Some(input) = self.input_ref.cast::<HtmlInputElement>() {
// start the worker off!
self.worker.send(WorkerInput {
n: input.value_as_number() as u32,
});
}
}
Self::Message::WorkerMsg(output) => {
// the worker is done!
self.fibonacci_output = format!("Fibonacci value: {}", output.value);
}
}

true
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<>
<h1>{ "Web worker demo" }</h1>
<p>{ "Submit a value to calculate, then increase the counter on the main thread!"} </p>
<p>{ "Large numbers will take some time!" }</p>
<h3>{ "Output: " } { &self.fibonacci_output }</h3>
<br />
<input ref={self.input_ref.clone()} type="number" value="44" max="50"/>
<button onclick={ctx.link().callback(|_| Message::RunWorker)}>{ "submit" }</button>
<br /> <br />
<h3>{ "Main thread value: " } { self.clicker_value }</h3>
<button onclick={ctx.link().callback(|_| Message::Click)}>{ "click!" }</button>
</>
}
}
}
19 changes: 19 additions & 0 deletions examples/web_worker_fib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![recursion_limit = "1024"]
#![allow(clippy::large_enum_variant)]

pub mod agent;
pub mod app;
use app::Model;
use wasm_bindgen::prelude::*;
use yew_agent::Threaded;

#[wasm_bindgen(start)]
pub fn start() {
use js_sys::{global, Reflect};

if Reflect::has(&global(), &JsValue::from_str("window")).unwrap() {
yew::start_app::<Model>();
} else {
agent::Worker::register();
}
}
12 changes: 12 additions & 0 deletions examples/web_worker_fib/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Yew web worker demo</title>
<script src="wasm.js"></script>
<script type="application/javascript">wasm_bindgen('wasm_bg.wasm');</script>
</head>

<body>
</body>
</html>

0 comments on commit c0f584c

Please sign in to comment.