chickadee » jiffi » define-armor-type

(define-armor-type ...)syntax

Defines a record type that can wrap a C struct/union or an array of structs/unions, and defines some basic procedures related to the record type. Also generates type declarations for those procedures, except for extra slot getters and setters (if there are any).

Usage:

(define-armor-type ARMOR-NAME
  pred:     PRED
  wrap:     WRAP
  unwrap:   UNWRAP
  children: CHILDREN               ; optional, default #t
  locking:  LOCK-EXPR              ; optional
  ;; Extra slots are optional
  (SLOT SLOT-GETTER SLOT-SETTER)   ; SLOT-SETTER is optional
  ...)

ARMOR-NAME is the record type name to define, using define-record-type.

PRED is the procedure name to define as the type predicate, which returns #t if passed an instance of this armor type, or #f if passed anything else.

WRAP is the procedure name to define as the armor wrapper, which returns a new armor instance that wraps some bare data.

UNWRAP is the procedure name to define as the armor unwrapper, which returns a pointer or locative to the bare data, or #f if it is null.

CHILDREN is a boolean that specifies the default value of whether instances of this armor type track their children, so that the children can be nullified when the instance is freed or nullified. See armor-tracks-children?.

LOCK-EXPR can be either (make-armor-lock) to make instances of this armor type thread safe by default, or #f to make the type not thread-safe by default. See "When should I enable armor thread safety?" in the Getting Started guide for more information. You can also use armor-lock-set! to enable or disable thread safety for a single armor instance.

Each SLOT is an optional extra slot in the record type, which you can use for your own purposes, for example to hold metadata. An extra slot can hold any Scheme object.

If you are defining armor for a C array, and you want to use define-array-allocators, it is recommended that the first extra slot is used to hold the array length. The slot name does not matter, only that it is the first.

Each SLOT-GETTER and SLOT-SETTER are the procedure names to define as the slot getter and setter. If SLOT-SETTER is omitted, no setter procedure will be defined, and that slot will be read-only (it can only be set when the armor is created with WRAP). If SLOT-SETTER is the form (setter SLOT-GETTER), no setter procedure will be defined, but that slot will be settable using (set! (SLOT-GETTER armor) value). If you want to have a setter procedure and also make the getter settable with set!, use (set! (setter SLOT-GETTER) SLOT-SETTER) after defining the armor type (see example).

If you define any extra slots, you may also want to provide SLOT-DEFAULTs if you use define-struct-allocators or define-array-allocators.

The record type will also contain one or more private slots which are used internally by Jiffi. The number and order of slots may change. Only use the slot getters and setters to access the slots. Do not rely on the slot layout staying the same!

Examples:

;; Armor for a C struct/union
(define-armor-type event
  pred: event?
  wrap: wrap-event
  unwrap: unwrap-event
  (extra1  event-extra1  (setter event-extra1))
  (extra2  event-extra2  event-extra2-set!))

;; Also make extra2 settable with (set! (event-extra2 armor) value)
(set! (setter event-extra2) event-extra2-set!)

;; Armor for a C array
(define-armor-type event-array
  pred: event-array?
  wrap: wrap-event-array
  unwrap: unwrap-event-array
  locking: (make-armor-lock)
  (length  event-array-length) ; first extra slot holds the length
  (extra1  event-array-extra1  (setter event-array-extra1)))