Skip to content

Commit 45ba35a

Browse files
committed
add parameter to emscripten_set_main_loop to optionally simulate an infinite loop by throwing an exception (like glutMainLoop)
1 parent 3a156a3 commit 45ba35a

15 files changed

+78
-14
lines changed

src/library_browser.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ mergeInto(LibraryManager.library, {
402402
}, millis);
403403
},
404404

405-
emscripten_set_main_loop: function(func, fps) {
405+
emscripten_set_main_loop: function(func, fps, simulateInfiniteLoop) {
406406
Module['noExitRuntime'] = true;
407407

408408
var jsFunc = FUNCTION_TABLE[func];
@@ -462,6 +462,10 @@ mergeInto(LibraryManager.library, {
462462
}
463463
}
464464
Browser.mainLoop.scheduler();
465+
466+
if (simulateInfiniteLoop) {
467+
throw 'emscripten_set_main_loop simulating infinite loop by throwing so we get right into the JS event loop';
468+
}
465469
},
466470

467471
emscripten_cancel_main_loop: function() {

system/include/emscripten/emscripten.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,30 @@ extern void emscripten_async_run_script(const char *script, int millis);
4646
* code assumes that), so you can break the code up into
4747
* asynchronous callbacks, but you must pause the main
4848
* loop until they complete.
49+
*
50+
* @simulate_infinite_loop If true, this function will throw an
51+
* exception in order to stop execution of the caller. This
52+
* will lead to the main loop being entered instead of code
53+
* after the call to emscripten_set_main_loop being run, which
54+
* is the closest we can get to simulating an infinite loop
55+
* (we do something similar in glutMainLoop in GLUT). If this
56+
* parameter is false, then the behavior is the same as it
57+
* was before this parameter was added to the API, which is
58+
* that execution continues normally. Note that in both cases
59+
* we do not run global destructors, atexit, etc., since we
60+
* know the main loop will still be running, but if we do
61+
* not simulate an infinite loop then the stack will be unwinded.
62+
* That means that if simulate_infinite_loop is false, and
63+
* you created an object on the stack, it will be cleaned up
64+
* before the main loop will be called the first time.
4965
*/
5066
#if EMSCRIPTEN
51-
extern void emscripten_set_main_loop(void (*func)(), int fps);
67+
extern void emscripten_set_main_loop(void (*func)(), int fps, int simulate_infinite_loop);
5268
extern void emscripten_pause_main_loop();
5369
extern void emscripten_resume_main_loop();
5470
extern void emscripten_cancel_main_loop();
5571
#else
56-
#define emscripten_set_main_loop(func, fps) \
72+
#define emscripten_set_main_loop(func, fps, simulateInfiniteLoop) \
5773
while (1) func();
5874
#endif
5975

tests/emscripten_api_browser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void mainey() {
5353
void four(void *arg) {
5454
assert((int)arg == 43);
5555
printf("four!\n");
56-
emscripten_set_main_loop(mainey, 0);
56+
emscripten_set_main_loop(mainey, 0, 0);
5757
}
5858

5959
void __attribute__((used)) third() {
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <stdio.h>
2+
#include <string.h>
3+
#include <emscripten.h>
4+
5+
struct Class {
6+
static Class *instance;
7+
8+
int x;
9+
10+
Class() : x(0) {}
11+
12+
void print() {
13+
char buf[18];
14+
memset(buf, 0, 18); // clear stack. if we did not simulate infinite loop, this clears x and is a bug!
15+
x += buf[7];
16+
17+
printf("waka %d\n", x++);
18+
19+
if (x == 7) {
20+
int result = x;
21+
REPORT_RESULT();
22+
}
23+
}
24+
25+
static void callback() {
26+
instance->print();
27+
}
28+
29+
void start() {
30+
instance = this;
31+
emscripten_set_main_loop(Class::callback, 3, 1); // important if we simulate an infinite loop here or not
32+
}
33+
};
34+
35+
Class *Class::instance = NULL;
36+
37+
int main() {
38+
Class().start();
39+
return 1;
40+
}
41+

tests/emscripten_fs_api_browser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ int main() {
6969
onLoaded,
7070
onError);
7171

72-
emscripten_set_main_loop(wait_wgets, 0);
72+
emscripten_set_main_loop(wait_wgets, 0, 0);
7373

7474
return 0;
7575
}

tests/enet_client.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ int main (int argc, char ** argv)
9494
"console.log('added.');");
9595
#endif
9696

97-
emscripten_set_main_loop(main_loop, 1);
97+
emscripten_set_main_loop(main_loop, 1, 1);
9898

9999
return 1;
100100
}

tests/enet_server.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ int main (int argc, char ** argv)
9292
exit (EXIT_FAILURE);
9393
}
9494

95-
emscripten_set_main_loop(main_loop, 1);
95+
emscripten_set_main_loop(main_loop, 1, 1);
9696

9797
return 1;
9898
}

tests/runner.py

+3
Original file line numberDiff line numberDiff line change
@@ -8664,6 +8664,9 @@ def btest(self, filename, expected=None, reference=None, reference_slack=0, args
86648664
def test_emscripten_api(self):
86658665
self.btest('emscripten_api_browser.cpp', '1')
86668666

8667+
def test_emscripten_api_infloop(self):
8668+
self.btest('emscripten_api_browser_infloop.cpp', '7')
8669+
86678670
def test_emscripten_fs_api(self):
86688671
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) # preloaded *after* run
86698672
self.btest('emscripten_fs_api_browser.cpp', '1')

tests/sdl_canvas_palette_2.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ int main() {
6868

6969
//Animation
7070
printf("you should see red gradient animation\n");
71-
emscripten_set_main_loop(animatePalette, 0);
71+
emscripten_set_main_loop(animatePalette, 0, 1);
7272

7373
SDL_Quit();
7474

tests/sdl_mouse.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,6 @@ void main_2(void* arg) {
6464
emscripten_run_script("window.simulateMouseEvent(30, 77, -1)"); // move some more
6565
emscripten_run_script("window.simulateMouseEvent(30, 77, 1)"); // trigger the end
6666

67-
emscripten_set_main_loop(one, 0);
67+
emscripten_set_main_loop(one, 0, 0);
6868
}
6969

tests/sdl_quit.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ int main() {
2626
SDL_Init(SDL_INIT_VIDEO);
2727
SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
2828

29-
emscripten_set_main_loop(one, 0);
29+
emscripten_set_main_loop(one, 0, 0);
3030

3131
emscripten_run_script("setTimeout(function() { window.close() }, 2000)");
3232
}

tests/websockets.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ int main(void)
115115
}
116116

117117
#if EMSCRIPTEN
118-
emscripten_set_main_loop(iter, 0);
118+
emscripten_set_main_loop(iter, 0, 0);
119119
#else
120120
while (!done) iter(NULL);
121121
#endif

tests/websockets_bi.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ int main(void)
124124
"iframe.src = 'side.html';"
125125
"document.body.appendChild(iframe);"
126126
"console.log('added.');");
127-
emscripten_set_main_loop(iter, 0);
127+
emscripten_set_main_loop(iter, 0, 0);
128128
#else
129129
while (!done) iter(NULL);
130130
#endif

tests/websockets_bi_listener.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ int main(void)
141141
"iframe.src = 'side.html';"
142142
"document.body.appendChild(iframe);"
143143
"console.log('added.');");
144-
emscripten_set_main_loop(iter, 0);
144+
emscripten_set_main_loop(iter, 0, 0);
145145
#else
146146
while (!done) iter(NULL);
147147
#endif

tests/websockets_gethostbyname.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ int main(void)
122122
}
123123

124124
#if EMSCRIPTEN
125-
emscripten_set_main_loop(iter, 0);
125+
emscripten_set_main_loop(iter, 0, 0);
126126
#else
127127
while (!done) iter(NULL);
128128
#endif

0 commit comments

Comments
 (0)