diff --git a/api-testcases/test-get-context.c b/api-testcases/test-get-context.c new file mode 100644 index 00000000..4c0b8c82 --- /dev/null +++ b/api-testcases/test-get-context.c @@ -0,0 +1,26 @@ +/*=== +concat: foobarquux +still here +===*/ + +void test(duk_context *ctx) { + duk_context *new_ctx; + + (void) duk_push_new_thread(ctx); + new_ctx = duk_get_context(ctx, -1); + + duk_push_string(new_ctx, "foo"); + duk_push_string(new_ctx, "bar"); + duk_push_string(new_ctx, "quux"); + duk_concat(new_ctx, 3); + printf("concat: %s\n", duk_get_string(new_ctx, -1)); + + /* This duk_pop() makes the new thread unreachable (assuming there + * is no other reference to it), so new_ctx is no longer valid + * afterwards. + */ + duk_pop(ctx); + + printf("still here\n"); +} + diff --git a/api-testcases/test-push-thread.c b/api-testcases/test-push-thread.c new file mode 100644 index 00000000..2c14f06d --- /dev/null +++ b/api-testcases/test-push-thread.c @@ -0,0 +1,31 @@ +/*=== +duk_is_object(1) = 1 +duk_is_thread(1) = 1 +top=2 +concat: foobarquux +done +===*/ + +void test(duk_context *ctx) { + int thr_idx; + duk_context *new_ctx; + + duk_push_int(ctx, 123); /* dummy */ + + thr_idx = duk_push_new_thread(ctx); + printf("duk_is_object(%d) = %d\n", thr_idx, duk_is_object(ctx, thr_idx)); + printf("duk_is_thread(%d) = %d\n", thr_idx, duk_is_thread(ctx, thr_idx)); + printf("top=%d\n", duk_get_top(ctx)); + + /* use the thread (context) value stack */ + new_ctx = duk_get_context(ctx, thr_idx); + duk_push_string(new_ctx, "foo"); + duk_push_string(new_ctx, "bar"); + duk_push_string(new_ctx, "quux"); + duk_concat(new_ctx, 3); + printf("concat: %s\n", duk_get_string(new_ctx, -1)); + + /* make new thread unreachable, so it gets GC'd */ + duk_set_top(ctx, 0); + printf("done\n"); +} diff --git a/website/api/duk_get_context.txt b/website/api/duk_get_context.txt new file mode 100644 index 00000000..8e32a4b4 --- /dev/null +++ b/website/api/duk_get_context.txt @@ -0,0 +1,36 @@ +=proto +duk_context *duk_get_context(duk_context *ctx, int index); + +=stack +[ ... val! ... ] + +=summary +

Get a context pointer for a Duktape thread at index. If the +value at index is not a Duktape thread or the index is invalid, +returns NULL.

+ +

The returned context pointer is only valid while the Duktape thread +is reachable from a garbage collection point of view.

+ +=example +duk_context *new_ctx; + +/* Create a new thread and get a context pointer. */ + +(void) duk_push_new_thread(ctx); +new_ctx = duk_get_context(ctx, -1); + +/* You can use new_ctx as long as the related thread is reachable + * from a garbage collection point of view. + */ + +duk_push_string(new_ctx, "foo"); + +/* This duk_pop() makes the new thread unreachable (assuming there + * is no other reference to it), so new_ctx is no longer valid + * afterwards. + */ + +duk_pop(ctx); + +/* Using new_ctx here may cause a crash. */ diff --git a/website/api/duk_push_new_thread.txt b/website/api/duk_push_new_thread.txt new file mode 100644 index 00000000..20890484 --- /dev/null +++ b/website/api/duk_push_new_thread.txt @@ -0,0 +1,22 @@ +=proto +int duk_push_new_thread(duk_context *ctx); + +=stack +[ ... ] -> [ ... thr! ] + +=summary +

Push a new Duktape thread (context, coroutine) to the stack. Returns +non-negative index (relative to stack bottom) of the pushed thread. +The new thread will be associated with the same Duktape heap as the +argument ctx.

+ +

To interact with the new thread with the Duktape API, use +duk_get_context() to get +a context pointer for API calls.

+ +=example +int thr_idx; +duk_context *new_ctx; + +thr_idx = duk_push_new_thread(ctx); +new_ctx = duk_get_context(ctx, thr_idx);