Skip to content

Commit 7cb0494

Browse files
committed
add timer api test. Adjust event callbacks to call with less lag. Will now call inside a blocking call like twr_sleep.
1 parent d94d411 commit 7cb0494

File tree

8 files changed

+176
-9
lines changed

8 files changed

+176
-9
lines changed

examples/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ <h1>WebAssembly C/C++ Examples<br>Using twr-wasm</h1>
196196
<td>Unit tests for Audio Library. WARNING: Turn volume all the way down before running as some of the test sounds are very loud.</td>
197197
<td><a href="tests-audio/index.html">run</a><br><a href="tests-audio/index.html#async">run async</a></td>
198198
</tr>
199+
<tr>
200+
<td>tests-timer</td>
201+
<td>Unit tests for Timer Library.</td>
202+
<td><a href="tests-timer/index.html">run</a><br><a href="tests-timer/index.html#async">run async</a></td>
203+
</tr>
199204
</table>
200205

201206

examples/tests-timer/Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
# tested with mingw32-make using windows
3+
4+
CC := clang
5+
6+
# -nostdinc Disable standard #include directories, provided by twr-wasm
7+
# -nostdlib Disable standard c library, provided by twr-wasm
8+
TWRCFLAGS := --target=wasm32 -nostdinc -nostdlib -isystem ../../include
9+
10+
# -O0 Optimization off (default if no -O specified)
11+
# -O3 Optimization level 3
12+
# -Wall Warn all
13+
# -c compile w/o linking
14+
# -g for debug symbols (also good to use twrd.a -- debug twr.a lib -- and optimization off -- in this case)
15+
# -v verbose
16+
CFLAGS := -c -Wall -O3 $(TWRCFLAGS)
17+
CFLAGS_DEBUG := -c -Wall -g -O0 $(TWRCFLAGS)
18+
19+
.PHONY: all
20+
21+
all: tests-timer.wasm tests-timer-a.wasm
22+
23+
tests-timer.o: tests-timer.c
24+
$(CC) $(CFLAGS) $< -o $@
25+
26+
tests-timer.wasm: tests-timer.o
27+
wasm-ld tests-timer.o ../../lib-c/twr.a -o tests-timer.wasm \
28+
--no-entry --initial-memory=131072 --max-memory=131072 \
29+
--export=tests_timer
30+
31+
tests-timer-a.wasm: tests-timer.o
32+
wasm-ld tests-timer.o ../../lib-c/twr.a -o tests-timer-a.wasm \
33+
--no-entry --shared-memory --no-check-features --initial-memory=131072 --max-memory=131072 \
34+
--export=tests_timer
35+
36+
clean:
37+
rm -f *.o
38+
rm -f *.wasm
39+
40+

examples/tests-timer/index.html

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>twr-wasm timer tests</title>
5+
</head>
6+
<body>
7+
<div id="iodiv"></div>
8+
9+
<!-- importmap is used when this example is not bundled -->
10+
<script type="importmap">
11+
{
12+
"imports": {
13+
"twr-wasm": "../../lib-js/index.js"
14+
}
15+
}
16+
</script>
17+
18+
<script type="module">
19+
import {twrWasmModule, twrWasmModuleAsync, twrConsoleDiv} from "twr-wasm";
20+
21+
const e = document.getElementById("iodiv");
22+
const con = new twrConsoleDiv(e);
23+
let mod;
24+
// const params = new URLSearchParams(window.location.search); stopped using this due to bug in parcel v2.12
25+
if (window.location.hash=="#async") {
26+
mod = new twrWasmModuleAsync({io:{stderr: con, stdio: con}});
27+
await mod.loadWasm("./tests-timer-a.wasm");
28+
con.putStr("twrWasmModuleAsync\n");
29+
await mod.callC(["tests_timer", 1]);
30+
}
31+
else {
32+
mod = new twrWasmModule({io:{stderr: con, stdio: con}});
33+
await mod.loadWasm("./tests-timer.wasm");
34+
con.putStr("twrWasmModule\n");
35+
await mod.callC(["tests_timer", 0]);
36+
}
37+
38+
</script>
39+
</body>
40+
</html>
41+

examples/tests-timer/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"@parcel/resolver-default": {
3+
"packageExports": true
4+
},
5+
"alias": {
6+
"twr-wasm": "../../lib-js/index.js"
7+
},
8+
"dependencies": {
9+
"twr-wasm": "^2.5.0"
10+
}
11+
}

examples/tests-timer/tests-timer.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <stdio.h>
2+
#include <twr-crt.h>
3+
4+
int t1_count=0;
5+
int t2_count=0;
6+
int timer2_id;
7+
8+
// timer event callback (called once)
9+
__attribute__((export_name("on_timer1")))
10+
void on_timer1(int event_id) {
11+
t1_count++;
12+
printf("timer callback 1 entered (event id=%d, count=%d)\n", event_id, t1_count);
13+
14+
if (t2_count!=5)
15+
printf("twr_timer_repeat FAIL!!\n");
16+
else
17+
printf("test run complete\n");
18+
}
19+
20+
// timer event callback (called multiple times by different timers)
21+
__attribute__((export_name("on_timer2")))
22+
void on_timer2(int event_id) {
23+
t2_count++;
24+
printf("timer callback 2 entered (event id=%d, count=%d)\n", event_id, t2_count);
25+
26+
if (t2_count==5) {
27+
twr_timer_cancel(timer2_id);
28+
if (t1_count!=0)
29+
printf("twr_timer_single_shot FAIL!!\n");
30+
}
31+
}
32+
33+
int tests_timer(int is_async) {
34+
35+
printf("starting timer tests.\n");
36+
37+
int timer2=twr_register_callback("on_timer2");
38+
timer2_id=twr_timer_repeat(500, timer2);
39+
40+
int timer1=twr_register_callback("on_timer1");
41+
42+
if (is_async) {
43+
printf("going to sleep...\n");
44+
twr_sleep(1000);
45+
printf("awake from sleep!\n");
46+
47+
if (t2_count!=2) {
48+
printf("FAIL!! t2_count is %d\n", t2_count);
49+
}
50+
51+
twr_timer_single_shot(2000, timer1);
52+
}
53+
54+
else {
55+
twr_timer_single_shot(4000, timer1);
56+
}
57+
58+
return 0;
59+
}

source/twr-ts/twreventqueue.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,17 @@ export class twrEventQueueReceive {
4747
args.push(arg);
4848
}
4949

50-
this.pendingEventIDs.push(eventID);
51-
this.pendingEventArgs.push(args);
50+
if (!(eventID in twrEventQueueReceive.onEventCallbacks))
51+
throw new Error("internal error");
52+
53+
const onEventCallback=twrEventQueueReceive.onEventCallbacks[eventID];
54+
if (onEventCallback) {
55+
onEventCallback(eventID, ...args);
56+
}
57+
else { // events with not callback must be read, eg with waitEvent
58+
this.pendingEventIDs.push(eventID);
59+
this.pendingEventArgs.push(args);
60+
}
5261
}
5362

5463
private readMallocRemainder() {

source/twr-ts/twrlibrary.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {twrEventQueueReceive} from "./twreventqueue.js"
88

99
// TODO List
1010

11+
// doc event behavior
1112
// fix example/lib/out and .gitignore so correct build artifacts are checked in
12-
// add test cases for twr_timer_single_shot, twr_timer_repeat, and twr_timer_cancel
1313
// resolve fact that libraries with interfaces are passed in the "io" option. Eg Allow "libs" or other synonym.
1414
// current implementation has no libs: (akin to io:).
1515
// consider if twrcondummy should be removed. Search for TODO, there are multiple places needing fixing. Possible solutions:
@@ -19,13 +19,12 @@ import {twrEventQueueReceive} from "./twreventqueue.js"
1919
// (c) merge imports (this won't work because a complete set of functions might not be loaded by api user)
2020
// also search for "TODO!! This is here to make twrcondummy.ts"
2121
// changed conterm example to use debug -- either change back, or change index description
22-
// deal with twrConGetIDFromNameImpl. Note that twr_register_callback and twrConGetIDFromNameImpl are added in two different places. Unify?
22+
// deal with twrConGetIDFromNameImpl. Note that twr_register_callback and twrConGetIDFromNameImpl are added in two different places. Unify
2323
// change callingMod:IWasmModule|IWasmModuleAsync to IWasmBase ?
2424
// add IWasmBase instead of using twrWasmBase
2525
// add IWasmModuleBase ?
2626
// Consider and handle app exit (stop events from being posted post app exit)
2727
// Add postEvent example that includes arguments
28-
// finish new twrLibTimer APIs - C side, doc, etc.
2928
// Implement event loop processing (get_next_event, get_filter_event)
3029
// Issue with above: how do I get the event parameters?
3130
// implement event loop in twrWasmModule (currently only in twrWasmModuleAsync) ?

source/twr-ts/twrmod.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,14 @@ export class twrWasmModule extends twrWasmBase implements IWasmModule {
152152

153153
postEvent(eventID:number, ...params:number[]) {
154154
//TODO!! PostEvent into eventQueueSend, then processEvents -- to enable non callback events when i add them
155-
const onEventCallback=twrEventQueueReceive.onEventCallbacks[eventID];
156-
if (!onEventCallback)
155+
if (!(eventID in twrEventQueueReceive.onEventCallbacks))
157156
throw new Error("twrWasmModule.postEvent called with invalid eventID: "+eventID+", params: "+params);
158-
159-
onEventCallback(eventID, ...params);
157+
158+
const onEventCallback=twrEventQueueReceive.onEventCallbacks[eventID];
159+
if (onEventCallback)
160+
onEventCallback(eventID, ...params);
161+
else
162+
throw new Error("twrWasmModule.postEvent called with undefined callback. eventID: "+eventID+", params: "+params);
160163
}
161164

162165
peekEvent(eventName:string) {

0 commit comments

Comments
 (0)