Skip to content

Commit

Permalink
Support suspension linger (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
kasperisager authored Jun 21, 2024
1 parent a4f7413 commit 98d2375
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 13 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ target_link_libraries(
hex
)

if(MSVC)
target_compile_options(
bare
PRIVATE
/experimental:c11atomics
)
endif()

add_library(bare_shared SHARED)

set_target_properties(
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ An object containing the version strings of Bare and its dependencies.

Immediately terminate the process or current thread with an exit status of `code` which defaults to `Bare.exitCode`.

#### `Bare.suspend()`
#### `Bare.suspend([linger])`

Suspend the process and all threads. This will emit a `suspend` event signalling that all work should stop immediately. When all work has stopped and the process would otherwise exit, an `idle` event will be emitted. If the process is not resumed from an `idle` event listener and no additional work is scheduled, the loop will block until the process is resumed. If additional work is scheduled from an `idle` event, the `idle` event will be emitted again once all work has stopped unless the process was resumed.

Expand Down Expand Up @@ -122,7 +122,7 @@ Emitted after the process or current thread has terminated and just before the J
> Bare.prependListener('teardown', () => { ... })
> ```
#### `Bare.on('suspend')`
#### `Bare.on('suspend', linger)`
Emitted when the process or current thread is suspended. Any in-progress or outstanding work, such as network activity or file system access, should be deferred, cancelled, or paused when the `suspend` event is emitted and no additional work may be scheduled.
Expand Down
4 changes: 2 additions & 2 deletions include/bare.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ typedef struct bare_options_s bare_options_t;
typedef void (*bare_before_exit_cb)(bare_t *);
typedef void (*bare_exit_cb)(bare_t *);
typedef void (*bare_teardown_cb)(bare_t *);
typedef void (*bare_suspend_cb)(bare_t *);
typedef void (*bare_suspend_cb)(bare_t *, int linger);
typedef void (*bare_idle_cb)(bare_t *);
typedef void (*bare_resume_cb)(bare_t *);
typedef void (*bare_thread_cb)(bare_t *, js_env_t *);
Expand Down Expand Up @@ -77,7 +77,7 @@ bare_run (bare_t *bare);
* process. It's safe to call this function from any thread.
*/
int
bare_suspend (bare_t *bare);
bare_suspend (bare_t *bare, int linger);

/**
* Resume the process as soon as possible. If the process is not yet idle after
Expand Down
4 changes: 3 additions & 1 deletion src/bare.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ bare_run (bare_t *bare) {
}

int
bare_suspend (bare_t *bare) {
bare_suspend (bare_t *bare, int linger) {
bare->process.runtime->linger = linger;

return uv_async_send(&bare->process.runtime->signals.suspend);
}

Expand Down
8 changes: 4 additions & 4 deletions src/bare.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ class Bare extends EventEmitter {
function noop () {}
}

suspend () {
bare.suspend()
suspend (linger = 0) {
bare.suspend(linger)
}

resume () {
Expand Down Expand Up @@ -169,10 +169,10 @@ class Bare extends EventEmitter {
this.emit('teardown')
}

_onsuspend () {
_onsuspend (linger) {
this.suspended = true

this.emit('suspend')
this.emit('suspend', linger)
}

_onidle () {
Expand Down
24 changes: 20 additions & 4 deletions src/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ bare_runtime_on_uncaught_exception (js_env_t *env, js_value_t *error, void *data
err = js_get_global(env, &global);
assert(err == 0);

js_call_function(env, global, fn, 1, (js_value_t *[]){error}, NULL);
js_call_function(env, global, fn, 1, &error, NULL);

err = js_close_handle_scope(env, scope);
assert(err == 0);
Expand Down Expand Up @@ -270,14 +270,18 @@ bare_runtime_on_suspend (bare_runtime_t *runtime) {
err = js_get_global(env, &global);
assert(err == 0);

js_call_function(env, global, fn, 0, NULL, NULL);
js_value_t *linger;
err = js_create_int32(env, runtime->linger, &linger);
assert(err == 0);

js_call_function(env, global, fn, 1, &linger, NULL);

err = js_close_handle_scope(env, scope);
assert(err == 0);

if (bare_runtime_is_main_thread(runtime)) {
if (runtime->process->on_suspend) {
runtime->process->on_suspend((bare_t *) runtime->process);
runtime->process->on_suspend((bare_t *) runtime->process, runtime->linger);
}
}
}
Expand Down Expand Up @@ -675,9 +679,20 @@ bare_runtime_suspend (js_env_t *env, js_callback_info_t *info) {

bare_runtime_t *runtime;

err = js_get_callback_info(env, info, NULL, NULL, NULL, (void **) &runtime);
js_value_t *argv[1];
size_t argc = 1;

err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &runtime);
assert(err == 0);

assert(argc == 1);

int32_t linger;
err = js_get_value_int32(env, argv[0], &linger);
assert(err == 0);

runtime->linger = linger;

uv_ref((uv_handle_t *) &runtime->signals.suspend);

err = uv_async_send(&runtime->process->runtime->signals.suspend);
Expand Down Expand Up @@ -886,6 +901,7 @@ bare_runtime_setup (uv_loop_t *loop, bare_process_t *process, bare_runtime_t *ru
runtime->suspended = false;
runtime->exiting = false;
runtime->terminated = false;
runtime->linger = 0;

err = uv_async_init(runtime->loop, &runtime->signals.suspend, bare_runtime_on_suspend_signal);
assert(err == 0);
Expand Down
3 changes: 3 additions & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define BARE_TYPES_H

#include <js.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <uv.h>

Expand Down Expand Up @@ -33,6 +34,8 @@ struct bare_runtime_s {
bool suspended;
bool exiting;
bool terminated;

atomic_int linger;
};

struct bare_process_s {
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ list(APPEND tests
suspend-resume-from-thread.js
suspend-resume-on-idle.js
suspend-resume-on-suspend.js
suspend-resume-with-linger.js
thread.js
thread-join.js
thread-source.js
Expand Down
17 changes: 17 additions & 0 deletions test/suspend-resume-with-linger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* global Bare */
const assert = require('bare-assert')

Bare
.on('suspend', (linger) => {
console.log('emit suspend')
assert(linger === 1000)
})
.on('idle', () => {
assert(false, 'Should not idle')
})
.on('resume', () => {
console.log('emit resume')
})

Bare.suspend(1000)
Bare.resume()

0 comments on commit 98d2375

Please sign in to comment.