No matching definitions.

tur/image

stdlib/image.tur

application image dumps via serializable continuations.

A warm-start facility in the style of Lisp save-lisp-and-die, Smalltalk image saves, and Emacs pdumper: capture a post-init continuation with Phase 21's serial-shift, write it to disk framed by a self-validating 72-byte header, and on a later run restore it instead of paying init again.

The on-disk format is a TurImageHeader (see src/runtime/image.h -- magic/version/build-stamp/payload-len/crc) followed by the TSER payload bytes produced by Phase 21's serial codegen. The build stamp (a SHA-256 of the running executable) pins an image to the binary that wrote it: a foreign or stale image is rejected cleanly (a 0 return), never resumed as garbage.

SECURITY: loading an image is equivalent to eval -- it resumes captured code. Treat image files as trusted executables; never load one from an untrusted source. See docs/guides/image-dumps-guide.md.

Since: Phase AI (application-image-dumps-plan)

defn

image/build-stamp

(image/build-stamp :int)

SHA-256 (32 bytes) of the running executable.

A malloc'd 32-byte buffer (caller frees with image/free-stamp) as an int pointer, or 0 if the executable image could not be read.

Since: Phase AI

defn

image/free-stamp

(image/free-stamp [p :int] :void)

free a build stamp returned by image/build-stamp.

defn

image/exists?

(image/exists? [path :cstr] :int)

1 if a readable file exists at path, else 0.

defn

image/hook-registry

(image/hook-registry [op :int arg :int] :int)

backing store for reload/finalize hooks (internal).

op 0: register a reload hook (arg = fat handle); returns the new count. op 1: run all reload hooks in registration order; returns the last result. op 2: register a finalize hook (arg = fat handle); returns the new count. op 3: run all finalize hooks in registration order; returns the last result.

defn

image/register-reload-hook!

(image/register-reload-hook! [^fat f :(fn [] int)] :int)

install a hook run on warm start before resume.

The hook is invoked after a valid image is selected and before the captured continuation resumes user code, in registration order. Use it to re-open files, re-bind sockets, or otherwise re-acquire OS handles that could not be serialised. Register at the top of main, before the with-image-cache call, so it is present on warm starts (which skip init).

fa zero-arg hook (fn [] int); the return value is ignored

The number of reload hooks registered so far.

Since: Phase AI (AI5.1)

defn

image/run-reload-hooks

(image/run-reload-hooks :int)

invoke every registered reload hook in order.

Returns the last hook's result (0 if none are registered). Called for you by the with-image-cache combinators on the warm path; call it directly only if you drive load-image! yourself.

Since: Phase AI (AI5.1)

defn

image/register-finalize-hook!

(image/register-finalize-hook! [^fat f :(fn [] int)] :int)

install a hook run just before a save.

The hook is invoked immediately before the image bytes are written, in registration order. Use it to flush buffers or release transient state that should not be captured. Register alongside the reload hooks at the top of main.

fa zero-arg hook (fn [] int); the return value is ignored

The number of finalize hooks registered so far.

Since: Phase AI (AI5.3)

defn

image/run-finalize-hooks

(image/run-finalize-hooks :int)

invoke every registered finalize hook in order.

Returns the last hook's result (0 if none are registered). Called for you by the with-image-cache combinators and save-image! just before writing bytes.

Since: Phase AI (AI5.3)

defmacro

defimage-reload-hook

(defimage-reload-hook [name & body])

define a named reload hook function.

Sugar for (defn name [] : int body): it pins the [] : int hook signature and gives the hook a stable top-level name (required -- the hook is invoked by name, never as an anonymous closure). It does NOT auto-register: install the hook with (image/register-reload-hook! name) at the top of main.

(defimage-reload-hook reopen-log
  (do (reopen-the-log!) 0))
;; ... in main, before with-image-cache-after-init:
(image/register-reload-hook! reopen-log)

Since: Phase AI (AI5.1)

defmacro

defimage-finalize-hook

(defimage-finalize-hook [name & body])

define a named finalize hook function.

Sugar for (defn name [] : int body), the save-side companion of defimage-reload-hook. Install with (image/register-finalize-hook! name).

Since: Phase AI (AI5.3)

defn

image/global-registry

(image/global-registry [op :int name :cstr ser :int deser :int bytes :ptr<void>] :int)

backing store for image globals (internal).

op 0: register (or replace by name) the ser/deser pair; returns the count. op 1: snapshot every registered global; returns a fresh bytes value

({len; data}, caller frees with image/free-bytes) or NULL if none.

op 2: restore globals from the bytes value in bytes; returns the number

of globals restored.

op 3: the registered count.

defn

image/free-bytes

(image/free-bytes [b :ptr<void>] :void)

free a bytes value returned by image/snapshot-globals.

defn

image/bytes-null?

(image/bytes-null? [b :ptr<void>] :bool)

true when a bytes/blob value is NULL.

defn

image/register-global!

(image/register-global! [name :cstr ^fat ser :(fn [] ptr<void>) ^fat deser :(fn [ptr<void>] int)] :int)

register a global's ser/deser pair by name.

The low-level registration behind defimage-global; call it directly only when you hand-roll the pair. A second registration under the same name replaces the first, so tracking at the top of main is idempotent.

namethe global's name, the key the image section is matched on
ser(fn [] ptr<void>): the global's current value as Serializable bytes
deser(fn [ptr<void>] int): overwrite the global from Serializable bytes

The number of globals registered so far.

Since: Phase AI (AI3.2)

defn

image/null-bytes

(image/null-bytes :ptr<void>)

the NULL bytes value (internal).

defn

image/global-count

(image/global-count :int)

how many image globals are registered.

Since: Phase AI (AI3.2)

defn

image/snapshot-globals

(image/snapshot-globals :ptr<void>)

serialise every registered global into one bytes value.

Returns a fresh {len; data} bytes value holding the globals section, or NULL when no global is registered. Free it with image/free-bytes. Called for you by save-image! and the with-image-cache combinators.

Since: Phase AI (AI3.3)

defn

image/bytes-of

(image/bytes-of [p :int] :ptr<void>)

reinterpret an int carrier as a bytes value (internal).

defn

image/restore-globals!

(image/restore-globals! [bytes :ptr<void>] :int)

overwrite registered globals from a globals section.

bytesa globals section as written by image/snapshot-globals (NULL is a no-op)

The number of globals restored.

Since: Phase AI (AI3.3)

defmacro

defimage-global

(defimage-global [name ty init])

declare a mutable global that rides in the image.

(defimage-global name :T initial) is (def ^mut name :T initial) plus the machinery that puts the global in the image: it also defines name/image-ser and name/image-deser (the global's Serializable instance, monomorphically -- T must have one) and name/image-track!, which registers the pair. Because compiled top-level forms do not run, the tracker is NOT called for you: put (image/track-globals! name ...) at the top of main, before the with-image-cache call, so the global is registered on both the cold start that writes the image and the warm start that restores it.

(defimage-global counter :int 0)
(defn do-init [] : int (do (set! counter 42) 0))
(defn main [] : int
  (do (image/track-globals! counter)
      (with-image-cache-after-init "app.img" do-init do-loop)))
;; a warm start sees counter = 42, not 0

Since: Phase AI (AI3.2)

defmacro

image/track-globals!

(image/track-globals! [& names])

register the named image globals (call at the top of main).

(image/track-globals! a b c) expands to the a/image-track! ... calls that defimage-global defined. Idempotent; evaluates to 0.

Since: Phase AI (AI3.2)

defn

image/crc32-

(image/crc32- [crc :int p :ptr<void> n :int] :int)

chainable CRC-32 (zlib convention) over n bytes at p (internal).

defn

image/write-image-file!

(image/write-image-file! [path :cstr k :ptr<void> stamp :int globals :ptr<void>] :int)

frame continuation k (+ globals) and write to path.

The C half of image/save-cont-to-file!: marshals k via the Phase 21 serial codec, writes the 72-byte header carrying stamp, the continuation bytes, and -- when globals is non-NULL -- the AI3 globals section ([int64 len][bytes]) that the header's globals_offset (byte 56) locates. payload_len covers both sections. The header's flags word carries TUR_IMAGE_FLAG_PAYLOAD_CRC and a u32 CRC-32 of the payload trails it (outside payload_len).

pathdestination path
kthe serial-continuation handle from serial-shift
stamp32-byte build stamp pointer (image/build-stamp), or 0 to zero-fill
globalsa globals section from image/snapshot-globals, or NULL for none

1 on success, 0 on failure (nil k, unwritable path, short write).

Since: Phase AI (AI3.3)

defn

image/save-cont-to-file!

(image/save-cont-to-file! [path :cstr k :ptr<void> stamp :int] :int)

serialise continuation k and write it to path.

Marshals k via the Phase 21 serial codec, frames the resulting payload with a 72-byte header carrying stamp, appends the registered image globals as a second section (AI3), and writes it to path.

pathdestination path
kthe serial-continuation handle from serial-shift
stamp32-byte build stamp pointer (image/build-stamp), or 0 to zero-fill

1 on success, 0 on failure (nil k, unwritable path, short write).

Since: Phase AI

defn

image/read-image-file

(image/read-image-file [path :cstr stamp :int] :ptr<void>)

read + validate an image into a blob (internal).

Validates magic / version / flags / header CRC and, when stamp is non-zero, the build stamp; holds payload_len to the file's real size; checks the payload CRC when the header says one follows; and checks the continuation bytes against this program's frame registry. Returns a malloc'd blob laid out as [int64 cont_len][cont bytes] [int64 globals_len][globals bytes] (globals_len is 0 for an image with no globals section), or NULL on any validation / I-O failure. The blob's head is exactly the buffer tur_serial_cont_deserialize consumes.

Since: Phase AI (AI3.3)

defn

image/loadable?

(image/loadable? [path :cstr stamp :int] :int)

1 if path is a valid image for stamp.

Runs every check image/load-resume-file! runs -- magic, version, header flags and CRC, the build stamp (which must equal stamp, the running binary's), the payload's length against the file and its CRC, and the continuation bytes against this program's frame registry -- so a 1 here means the load will resume rather than fail. A missing, corrupt, foreign or truncated image returns 0. Callers use it to decide whether to resume an image, so that a resumed value of 0 is never confused with a load failure.

Since: Phase AI

defn

image/blob-globals

(image/blob-globals [blob :ptr<void>] :ptr<void>)

the globals section inside a read blob (internal).

Returns a bytes view ({len; data}) into the blob, or NULL when the image carried no globals. The view borrows the blob; do not free it.

defn

image/blob-resume!

(image/blob-resume! [blob :ptr<void> v :int] :int)

deserialise the blob's continuation and resume it on v.

Consumes (frees) the blob. Returns the resumed continuation's value.

defn

image/load-resume-file!

(image/load-resume-file! [path :cstr stamp :int v :int] :int)

read + validate an image and resume it on v.

Validates magic / version / CRC. When stamp is non-zero, also requires the header build-stamp to equal it (build-stamp safety, AI4); pass 0 to skip the stamp check (the --unsafe-image-skip-build-check escape hatch). Registered image globals (AI3) are restored from the image's globals section BEFORE the continuation resumes.

pathsource path
stamp32-byte build-stamp pointer to enforce, or 0 to skip the check
vthe value to resume the captured continuation with

The resumed continuation's value on success (control transfers into the captured tail), or 0 on any validation/I-O failure (no resume occurs).

Since: Phase AI

defn

save-image!

(save-image! [path :cstr] :int)

capture the current continuation and write it to path.

Captures at the serial-shift site: the continuation is the rest of the enclosing serial-reset after this call. Returns 1 on a successful write. On its own the captured continuation is the empty (identity) tail; the useful capture happens via with-image-cache-after-init, which places the capture between an init phase and a long-running loop.

Since: Phase AI

defn

load-image!

(load-image! [path :cstr] :int)

read an image and resume the continuation it holds.

Validates magic/version/crc and the build stamp against the running binary. On a clean image, control transfers into the resumed continuation. On any validation failure returns 0 (no resume).

Note: a return of 0 is ambiguous -- it is also what a resumed continuation that evaluates to 0 returns. When the cold/warm decision matters, gate on image/loadable? first (as with-image-cache-after-init does) rather than on this value.

Since: Phase AI

defmacro

with-image-cache-after-init

(with-image-cache-after-init [path init loop])

the primary warm-start combinator (AIQ1).

On a cold start (no valid image): runs init, captures the continuation that runs loop, writes it to path, then runs loop. On a warm start (valid image present): skips init, restores the captured continuation, and jumps straight into loop.

pathimage cache path
inita fn [] run only on cold start (expensive setup)
loopa fn [] run on both paths (the steady-state work)

This is a macro, not a function: init and loop are spliced as call targets so the captured continuation tail (loop) is a call to a *named* top-level function. The serial-shift collector reconstructs frames by stable name, so the tail cannot be a heap closure -- it must be a named (serializable) continuation. Pass top-level defn names for init and loop.

For a *cross-process* warm start to resume correctly, loop must reduce to a serializable continuation (named frames, int/cstr/Serializable envs) -- the same constraint Serializable continuations impose on serial-shift.

Since: Phase AI

defn

with-image-cache

(with-image-cache [path :cstr ^fat body :(fn [] int)] :int)

single-body warm-start wrapper.

If a valid image exists, restore it; otherwise run body, then capture an image after body returns. Prefer with-image-cache-after-init unless body ends in a long-running loop you want to dump between iterations.

Since: Phase AI