Skip to content
Open
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
62 changes: 61 additions & 1 deletion examples/basic/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,56 @@
/* auto-generated by zig-addon */
/* eslint-disable */

export interface FibProgress {
current: number
total: number
}

export interface FileReadSummary {
path: string
bytes: number
text: string
}

export interface ParallelReadInput {
first_path: string
second_path: string
preview_bytes: number
}

export interface ParallelReadSummary {
first_bytes: number
second_bytes: number
total_bytes: number
preview: string
}

export interface AsyncMathInput {
left: number
right: number
scale: number
}

export interface AsyncMathResult {
sum: number
product: number
scaled_sum: number
}

export interface CountProgress {
current: number
total: number
}

export interface AbortSignal {
aborted: boolean
reason?: any
onabort: null | ((this: AbortSignal, event: any) => void)
addEventListener(name: string, listener: (this: AbortSignal, event: any) => any): void
removeEventListener(name: string, listener: (this: AbortSignal, event: any) => any): void
throwIfAborted?(): void
}

export interface FullField {
name: string
age: number
Expand Down Expand Up @@ -70,7 +120,17 @@ export declare function hello(name: string): string
export declare const text: string
export declare function throw_error(): void
export declare function fib(n: number): void
export declare function fib_async(n: number): Promise<void>
export declare function fib_async(n: number): Promise<number>
export declare function fib_async_progress(n: number, onEvent?: (event: FibProgress) => void): Promise<number>
export declare function read_file_async(path: string): Promise<string>
export declare function read_file_summary_async(path: string): Promise<FileReadSummary>
export declare function parallel_read_files_async(input: ParallelReadInput): Promise<ParallelReadSummary>
export declare function async_math_single(input: AsyncMathInput): Promise<AsyncMathResult>
export declare function async_void_thread(): Promise<void>
export declare function async_fail_thread(message: string): Promise<void>
export declare function count_async_progress_thread(total: number, onEvent?: (event: CountProgress) => void): Promise<number>
export declare function event_mode_progress_async(total: number, onEvent?: (event: CountProgress) => void): Promise<number>
export declare function abortable_count_async(total: number, signal: AbortSignal): Promise<number>
export declare function get_and_return_array(array: Array<number>): Array<number>
export declare function get_named_array(array: [number, boolean, string]): [number, boolean, string]
export declare function get_arraylist(array: Array<number>): Array<number>
Expand Down
199 changes: 199 additions & 0 deletions examples/basic/src/async.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
const napi = @import("napi");
const std = @import("std");

fn fibonacci(n: f64) f64 {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}

pub const FibProgress = struct {
current: f64,
total: f64,
};

pub const CountProgress = struct {
current: u32,
total: u32,
};

pub const AsyncMathInput = struct {
left: f64,
right: f64,
scale: f64,
};

pub const AsyncMathResult = struct {
sum: f64,
product: f64,
scaled_sum: f64,
};

pub const FileReadSummary = struct {
path: []u8,
bytes: usize,
text: []u8,
};

pub const ParallelReadInput = struct {
first_path: []u8,
second_path: []u8,
preview_bytes: usize,
};

pub const ParallelReadSummary = struct {
first_bytes: usize,
second_bytes: usize,
total_bytes: usize,
preview: []u8,
};

fn fibonacci_execute(data: f64) f64 {
return fibonacci(data);
}

fn fibonacci_execute_with_progress(ctx: napi.AsyncContext(FibProgress), data: f64) !f64 {
try ctx.emit(.{ .current = 0, .total = data });
const result = fibonacci(data);
try ctx.emit(.{ .current = data, .total = data });
return result;
}

fn read_file_execute(ctx: napi.AsyncContext(void), path: []u8) ![]u8 {
return try std.Io.Dir.cwd().readFileAlloc(ctx.io, path, ctx.allocator, .limited(1024 * 1024));
}

fn read_file_summary_execute(ctx: napi.AsyncContext(void), path: []u8) !FileReadSummary {
const text = try read_file_execute(ctx, path);
return .{
.path = path,
.bytes = text.len,
.text = text,
};
}

fn async_math_execute(input: AsyncMathInput) AsyncMathResult {
const sum = input.left + input.right;
return .{
.sum = sum,
.product = input.left * input.right,
.scaled_sum = sum * input.scale,
};
}

fn async_void_execute(_: void) void {}

fn async_fail_execute(message: []u8) !void {
return napi.Error.fromReason(message);
}

const ReadSlot = struct {
text: []u8 = &.{},
err: ?anyerror = null,
};

fn read_file_slot(ctx: napi.AsyncContext(void), path: []u8, slot: *ReadSlot) std.Io.Cancelable!void {
slot.text = std.Io.Dir.cwd().readFileAlloc(ctx.io, path, ctx.allocator, .limited(1024 * 1024)) catch |err| {
slot.err = err;
return;
};
}

fn append_preview(output: []u8, offset: *usize, text: []const u8, limit: usize) void {
const len = @min(text.len, limit);
@memcpy(output[offset.* .. offset.* + len], text[0..len]);
offset.* += len;
}

fn parallel_read_execute(ctx: napi.AsyncContext(void), input: ParallelReadInput) !ParallelReadSummary {
var first: ReadSlot = .{};
var second: ReadSlot = .{};

try ctx.group.concurrent(ctx.io, read_file_slot, .{ ctx, input.first_path, &first });
try ctx.group.concurrent(ctx.io, read_file_slot, .{ ctx, input.second_path, &second });
try ctx.awaitGroup();

if (first.err) |err| return err;
if (second.err) |err| return err;

const first_preview_len = @min(first.text.len, input.preview_bytes);
const second_preview_len = @min(second.text.len, input.preview_bytes);
const separator = "\n---\n";
const preview_len = first_preview_len + separator.len + second_preview_len;
const preview = try ctx.allocator.alloc(u8, preview_len);
var offset: usize = 0;
append_preview(preview, &offset, first.text, input.preview_bytes);
@memcpy(preview[offset .. offset + separator.len], separator);
offset += separator.len;
append_preview(preview, &offset, second.text, input.preview_bytes);

return .{
.first_bytes = first.text.len,
.second_bytes = second.text.len,
.total_bytes = first.text.len + second.text.len,
.preview = preview,
};
}

fn count_with_progress_execute(ctx: napi.AsyncContext(CountProgress), total: u32) !u32 {
var current: u32 = 0;
while (current <= total) : (current += 1) {
try ctx.emit(.{ .current = current, .total = total });
}
return total;
}

fn abortable_count_execute(ctx: napi.AsyncContext(void), total: u32) !u32 {
var current: u32 = 0;
while (current < total) : (current += 1) {
if (current % 1024 == 0) {
try ctx.checkCancelled();
}
}
try ctx.checkCancelled();
return total;
}

pub fn fib_async(n: f64) napi.Async(f64, .thread) {
return napi.Async(f64, .thread).from(n, fibonacci_execute);
}

pub fn fib_async_progress(n: f64) napi.AsyncWithEvents(f64, FibProgress, .single) {
return napi.AsyncWithEvents(f64, FibProgress, .single).from(n, fibonacci_execute_with_progress);
}

pub fn read_file_async(path: []u8) napi.Async([]u8, .thread) {
return napi.Async([]u8, .thread).from(path, read_file_execute);
}

pub fn read_file_summary_async(path: []u8) napi.Async(FileReadSummary, .thread) {
return napi.Async(FileReadSummary, .thread).from(path, read_file_summary_execute);
}

pub fn parallel_read_files_async(input: ParallelReadInput) napi.Async(ParallelReadSummary, .thread) {
return napi.Async(ParallelReadSummary, .thread).from(input, parallel_read_execute);
}

pub fn async_math_single(input: AsyncMathInput) napi.Async(AsyncMathResult, .single) {
return napi.Async(AsyncMathResult, .single).from(input, async_math_execute);
}

pub fn async_void_thread() napi.Async(void, .thread) {
return napi.Async(void, .thread).from({}, async_void_execute);
}

pub fn async_fail_thread(message: []u8) napi.Async(void, .thread) {
return napi.Async(void, .thread).from(message, async_fail_execute);
}

pub fn count_async_progress_thread(total: u32) napi.AsyncWithEvents(u32, CountProgress, .thread) {
return napi.AsyncWithEvents(u32, CountProgress, .thread).from(total, count_with_progress_execute);
}

pub fn event_mode_progress_async(total: u32) napi.AsyncWithEvents(u32, CountProgress, .event) {
return napi.AsyncWithEvents(u32, CountProgress, .event).from(total, count_with_progress_execute);
}

pub fn abortable_count_async(total: u32, signal: napi.AbortSignal) napi.Async(u32, .thread) {
_ = signal;
return napi.Async(u32, .thread).from(total, abortable_count_execute);
}
13 changes: 12 additions & 1 deletion examples/basic/src/hello.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const number = @import("number.zig");
const string = @import("string.zig");
const err = @import("err.zig");
const worker = @import("worker.zig");
const async_examples = @import("async.zig");
const array = @import("array.zig");
const object = @import("object.zig");
const function = @import("function.zig");
Expand All @@ -28,7 +29,17 @@ pub const text = string.text;
pub const throw_error = err.throw_error;

pub const fib = worker.fib;
pub const fib_async = worker.fib_async;
pub const fib_async = async_examples.fib_async;
pub const fib_async_progress = async_examples.fib_async_progress;
pub const read_file_async = async_examples.read_file_async;
pub const read_file_summary_async = async_examples.read_file_summary_async;
pub const parallel_read_files_async = async_examples.parallel_read_files_async;
pub const async_math_single = async_examples.async_math_single;
pub const async_void_thread = async_examples.async_void_thread;
pub const async_fail_thread = async_examples.async_fail_thread;
pub const count_async_progress_thread = async_examples.count_async_progress_thread;
pub const event_mode_progress_async = async_examples.event_mode_progress_async;
pub const abortable_count_async = async_examples.abortable_count_async;

pub const get_and_return_array = array.get_and_return_array;
pub const get_named_array = array.get_named_array;
Expand Down
19 changes: 14 additions & 5 deletions examples/basic/src/thread_safe_function.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,25 @@ fn sleepForFiveSeconds() void {
}

fn execute_thread_safe_function(tsfn: *napi.ThreadSafeFunction(Args, Return, true, 0)) void {
defer tsfn.release(.Release) catch {};
sleepForFiveSeconds();
tsfn.Ok(.{ 1, 2 }, .NonBlocking);
tsfn.Ok(.{ 1, 2 }, .NonBlocking) catch {};
}

fn execute_thread_safe_function_with_error(tsfn: *napi.ThreadSafeFunction(Args, Return, true, 0)) void {
defer tsfn.release(.Release) catch {};
sleepForFiveSeconds();
tsfn.Err(napi.Error.withReason("TSFN Error"), .NonBlocking);
tsfn.Err(napi.Error.withReason("TSFN Error"), .NonBlocking) catch {};
}

pub fn call_thread_safe_function(tsfn: *napi.ThreadSafeFunction(Args, Return, true, 0)) void {
_ = std.Thread.spawn(.{}, execute_thread_safe_function, .{tsfn}) catch @panic("Failed to spawn thread");
_ = std.Thread.spawn(.{}, execute_thread_safe_function_with_error, .{tsfn}) catch @panic("Failed to spawn thread");
pub fn call_thread_safe_function(tsfn: *napi.ThreadSafeFunction(Args, Return, true, 0)) !void {
try tsfn.acquire();
const worker = try std.Thread.spawn(.{}, execute_thread_safe_function, .{tsfn});
worker.detach();

try tsfn.acquire();
const worker_with_error = try std.Thread.spawn(.{}, execute_thread_safe_function_with_error, .{tsfn});
worker_with_error.detach();

try tsfn.release(.Release);
}
14 changes: 2 additions & 12 deletions examples/basic/src/worker.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ fn fibonacci(n: f64) f64 {
return fibonacci(n - 1) + fibonacci(n - 2);
}

fn fibonacci_execute(_: napi.Env, data: f64) void {
const result = fibonacci(data);

const allocator = std.heap.page_allocator;
const message = std.fmt.allocPrint(allocator, "Fibonacci result: {d}", .{result}) catch @panic("OOM");
defer allocator.free(message);
fn fibonacci_execute(data: f64) f64 {
return fibonacci(data);
}

fn fibonacci_on_complete(_: napi.Env, data: f64) void {
Expand All @@ -24,9 +20,3 @@ pub fn fib(env: napi.Env, n: f64) void {
const worker = napi.Worker(env, .{ .data = n, .Execute = fibonacci_execute, .OnComplete = fibonacci_on_complete });
worker.Queue();
}

pub fn fib_async(env: napi.Env, n: f64) napi.Promise {
const worker = napi.Worker(env, .{ .data = n, .Execute = fibonacci_execute, .OnComplete = fibonacci_on_complete });
const promise = worker.AsyncQueue();
return promise;
}
2 changes: 1 addition & 1 deletion examples/init/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export declare function add(left: number, right: number): number
export declare function hello(name: string): string
export declare const text: string
export declare function fib(n: number): void
export declare function fib_async(n: number): Promise<void>
export declare function fib_async(n: number): Promise<number>
export declare function get_and_return_array(array: Array<number>): Array<number>
export declare function get_named_array(array: [number, boolean, string]): [number, boolean, string]
export declare function get_arraylist(array: Array<number>): Array<number>
Expand Down
14 changes: 4 additions & 10 deletions examples/init/src/hello.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@ fn fibonacci(n: f64) f64 {
return fibonacci(n - 1) + fibonacci(n - 2);
}

fn fibonacci_execute(_: napi.Env, data: f64) void {
const result = fibonacci(data);

const allocator = std.heap.page_allocator;
const message = std.fmt.allocPrint(allocator, "Fibonacci result: {d}", .{result}) catch @panic("OOM");
defer allocator.free(message);
fn fibonacci_execute(data: f64) f64 {
return fibonacci(data);
}

fn fibonacci_on_complete(_: napi.Env, data: f64) void {
Expand Down Expand Up @@ -45,10 +41,8 @@ fn fib(env: napi.Env, n: f64) void {
worker.Queue();
}

fn fib_async(env: napi.Env, n: f64) napi.Promise {
const worker = napi.Worker(env, .{ .data = n, .Execute = fibonacci_execute, .OnComplete = fibonacci_on_complete });
const promise = worker.AsyncQueue();
return promise;
fn fib_async(n: f64) napi.Async(f64, .thread) {
return napi.Async(f64, .thread).from(n, fibonacci_execute);
}

fn get_and_return_array(array: []f32) []f32 {
Expand Down
Loading
Loading