|
| 1 | +<!doctype html><html><head><meta charset="utf-8"><title>Grol</title></head> |
1 | 2 | <!--
|
2 | 3 | Keep grol/wasm/grol_wasm.html and web-site/_includes/grol_wasm.html in sync
|
3 | 4 | Using `make sync` in web-site/
|
|
38 | 39 | </style>
|
39 | 40 | <script src="wasm_exec.js"></script>
|
40 | 41 | <script>
|
41 |
| - function debounce(func) { |
| 42 | + /** |
| 43 | + * A singular task ES6++ mutex |
| 44 | + * inspired by this https://blog.jcoglan.com/2016/07/12/mutexes-and-javascript/ |
| 45 | + */ |
| 46 | + class Lock { |
| 47 | + #isLocked = false |
| 48 | + #queue = [] |
| 49 | + constructor(){} |
| 50 | + |
| 51 | + sync(task) { |
| 52 | + console.log("SYNC") |
| 53 | + if (this.#isLocked) { |
| 54 | + console.log("Lock already has a task, ommiting another one at " + new Date().toString()) |
| 55 | + return |
| 56 | + } |
| 57 | + |
| 58 | + this.#queue.push(task) |
| 59 | + if (!this.#isLocked) this.#dequeue() |
| 60 | + } |
| 61 | + |
| 62 | + #dequeue() { |
| 63 | + this.#isLocked = true |
| 64 | + const next = this.#queue.shift() |
| 65 | + |
| 66 | + if (next) this.#execute(next) |
| 67 | + else this.#isLocked = false |
| 68 | + } |
| 69 | + |
| 70 | + async #execute(task) { |
| 71 | + const thisDequeue = () => this.#dequeue() |
| 72 | + task().then(thisDequeue, thisDequeue) |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + function debounce(func, ms = 100) { // 100ms debounce by default |
42 | 77 | let timeout
|
43 | 78 | return function (...args) {
|
44 | 79 | const context = this
|
45 | 80 | clearTimeout(timeout)
|
46 |
| - timeout = setTimeout(() => func.apply(context, args), 100) // 100ms debounce |
| 81 | + timeout = setTimeout(() => func.apply(context, args), ms) |
47 | 82 | }
|
48 | 83 | }
|
49 | 84 | if (!WebAssembly.instantiateStreaming) { // polyfill
|
|
68 | 103 | function formatError(error) {
|
69 | 104 | return `Error: ${error.message}`;
|
70 | 105 | }
|
71 |
| - let isRunning = false |
72 |
| - async function run() { |
73 |
| - if (isRunning) return; // Prevent running multiple times concurrently |
74 |
| - isRunning = true; |
| 106 | + |
| 107 | + async function _run() { |
75 | 108 | document.getElementById("runButton").disabled = true; // Disable button during execution
|
76 | 109 | try {
|
77 | 110 | // console.clear();
|
|
105 | 138 | } finally {
|
106 | 139 | inst = await WebAssembly.instantiate(mod, go.importObject)
|
107 | 140 | console.log('Instance reset:', inst)
|
108 |
| - if (isRunning) { |
109 |
| - isRunning = false; // Allow running again after reset |
110 |
| - document.getElementById("runButton").disabled = false; // Re-enable the button |
111 |
| - } |
| 141 | + document.getElementById("runButton").disabled = false; // Re-enable the button |
112 | 142 | }
|
113 | 143 | resizeTextarea(document.getElementById('input'));
|
114 | 144 | resizeTextarea(document.getElementById('output'));
|
115 | 145 | resizeTextarea(document.getElementById('errors'));
|
116 | 146 | }
|
117 |
| - const debounceRun = debounce(run) |
| 147 | + |
| 148 | + |
| 149 | + const lock = new Lock() |
| 150 | + const run = debounce(() => lock.sync(_run), 100) |
| 151 | + |
118 | 152 | document.addEventListener('DOMContentLoaded', (event) => {
|
119 | 153 | document.getElementById('input').addEventListener('keydown', function (e) {
|
120 |
| - if (e.key === 'Enter' && !isRunning) { |
121 |
| - debounceRun(); |
| 154 | + if (e.key === 'Enter') { |
| 155 | + run() |
122 | 156 | }
|
123 | 157 | });
|
124 | 158 | });
|
|
142 | 176 | m={"str key": a, PI: "pi", 42: "str val", 1e3: "a lot"}</textarea>
|
143 | 177 | </div>
|
144 | 178 | <div>
|
145 |
| - Hit enter or click <button onClick="debounceRun()" id="runButton" disabled>Run</button> (will also format the code, |
| 179 | + Hit enter or click <button onClick="run()" id="runButton" disabled>Run</button> (will also format the code, |
146 | 180 | also
|
147 | 181 | try <input type="checkbox" id="compact">compact)
|
148 | 182 | <button id="addParamButton">Share</button>
|
|
185 | 219 | document.getElementById('input').value = decodeURIComponent(paramValue)
|
186 | 220 | }
|
187 | 221 | </script>
|
| 222 | +</html> |
0 commit comments