std/worker

Standard Library documentation

isolated workers for shared-nothing parallel work.

Module

Name
std/worker
Area
Standard Library
Source
modules/std/worker.zzm

NAME

std/worker - isolated workers for shared-nothing parallel work.

SYNOPSIS

  from std/worker import Worker;

  async function __main__ () {
    let task := Worker.spawn(
      function ( x ) {
        return x * 2;
      },
      [ 21 ],
    );

    say await {
      task;
    };
  }

IMPLEMENTATION SUPPORT

This module is supported by all implementations of ZuzuScript.

DESCRIPTION

This runtime-supported module provides isolated workers for CPU-heavy or host-isolated work. Workers run in a fresh runtime and communicate with their parent by copying values through std/marshal. Worker transport is shared-nothing: parent and worker runtimes do not share mutable ZuzuScript values.

The worker boundary is intended for cooperating trusted code. It uses std/marshal.load, which may evaluate marshalled code records, so it must not be used as an untrusted data sandbox.

EXPORTS

Classes

  • Worker

    The worker namespace class.

  • Worker.spawn(callable, args?, ...options)

    Parameters: callable is the worker function, args is an optional array of arguments, and options configures the worker. Returns: Task. Starts one worker job and resolves to the worker result.

    If the worker throws, cancellation is requested, or marshalling fails, awaiting the task throws the corresponding exception value.

  • Worker.spawn_handle(callable, args?, ...options)

    Parameters: callable is the worker function, args is an optional array of arguments, and options configures the worker. Returns: WorkerHandle. Starts a worker with an explicit bidirectional message channel.

    This method is available in implementations that support message passing workers. Scripts that need to be portable to an older host may check Worker can "spawn_handle" before using it.

  • WorkerHandle.send(value)

    Parameters: value is any marshalable value. Returns: Task. Marshals and sends value to the worker inbox.

  • WorkerHandle.recv()

    Parameters: none. Returns: Task. Resolves to the next worker-to-parent message.

  • WorkerHandle.close()

    Parameters: none. Returns: Task. Half-closes the parent-to-worker send direction.

  • WorkerHandle.cancel(reason?)

    Parameters: reason is an optional cancellation reason. Returns: Task. Requests worker cancellation and cancels the result task.

  • WorkerHandle.result()

    Parameters: none. Returns: Task. Returns the worker result task.

  • WorkerHandle.status()

    Parameters: none. Returns: String. Returns the status of the result task.

  • WorkerHandle.done()

    Parameters: none. Returns: Boolean. Returns true when the result task has fulfilled, rejected, or been cancelled.

  • inbox.send(value)

    Parameters: value is any marshalable value. Returns: Task. Worker-side method for sending a message to the parent.

  • inbox.recv()

    Parameters: none. Returns: Task. Worker-side method for receiving the next parent message.

  • inbox.close()

    Parameters: none. Returns: Task. Half-closes the worker-to-parent send direction.

WORKER OPTIONS

Workers inherit every denied capability from the parent runtime. A worker option can deny additional capabilities, but cannot relax a parent denial.

Supported options are:

  • deny_fs: Boolean
  • deny_net: Boolean
  • deny_proc: Boolean
  • deny_db: Boolean
  • deny_clib: Boolean
  • deny_gui: Boolean
  • deny_worker: Boolean
  • deny_js: Boolean
  • deny_perl: Boolean

For example:

  let task := Worker.spawn(
    function () {
      from std/io import Path;
      return new Path("secret.txt").slurp_utf8();
    },
    [],
    deny_fs: true,
  );

MESSAGE EXAMPLE

  let handle := Worker.spawn_handle(
    async function ( inbox ) {
      let value := await {
        inbox.recv();
      };
      await {
        inbox.send( value * 2 );
      };
      inbox.close();
      return "done";
    },
    [],
  );

  await {
    handle.send(21);
  };
  say await {
    handle.recv();
  };
  say await {
    handle.result();
  };

PORTABILITY NOTES

Host runtimes use their own worker primitives. If std/worker imports successfully, workers are assumed to be available.

Live std/task.Channel, Task, and other runtime-backed resources are not transferable unless std/marshal explicitly supports them.

COPYRIGHT AND LICENCE

std/worker is copyright Toby Inkster.

It is free software; you may redistribute it and/or modify it under the terms of either the Artistic License 1.0 or the GNU General Public License version 2.