Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support suspension linger #31

Merged
merged 2 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()