Skip to content

Instantly share code, notes, and snippets.

@alexcrichton
Created March 31, 2025 17:38
Show Gist options
  • Save alexcrichton/99c9d63cfd15673cfe2fa34a7993e20b to your computer and use it in GitHub Desktop.
Save alexcrichton/99c9d63cfd15673cfe2fa34a7993e20b to your computer and use it in GitHub Desktop.
#include <stdint.h>
#define P3_TASK_VERSION1 1
typedef struct p3_task_v1 {
// For now it's `P3_TASK_VERSION1`, and this indicates what fields are present
// in this structure. Accessing a vX field must check that `version` here is
// `>= X`.
int version;
// Embedder-defined pointer passed to callbacks below. Exported tasks control
// this and it's opaque to other users.
void *ptr;
// For the current exported task, register `callback(code, ptr)` to happen
// when `waitable` gets signaled. Basically add `waitable` to a waitable set
// and arrange for the callback to get invoked when the current exported task
// gets the notification the waitable is ready.
//
// If already registered this removes the previous callback and returns its
// `ptr` field. If waitable was not previously registered this returns `NULL`.
void* (*waitable_register)(
void *p3_task_ptr, // `p3_task_v1.ptr`
uint32_t waitable,
void(*complete)(uint32_t code, void *ptr),
void *ptr
);
// Dual of the above, but removes it from the waitable set and/or tracking.
//
// Returns `NULL` if `waitable` was not registered or returns the `ptr` field
// provided during registration.
void *(*waitable_unregister)(
void *p3_task_ptr, // `p3_task_v1.ptr`
uint32_t waitable
);
} p3_task_v1;
// Sets the return value of `p3_task_get` below tot he provided pointer.
//
// This sets a `static` in-memory to this value. This is called whenever an
// exported tasks starts work to initialize the memory. When an exported task
// finishes work it would probably set this back to NULL.
//
// The lifetime of the `task` pointer must be the same as the lifetime of the
// exported task itself.
void p3_task_set(struct p3_task_v1 *task);
// Get the task set by `p3_task_set` prior.
//
// The lifetime of the returned pointer is bound to the currently running task.
// Callers should assert this is not-null.
//
// This is used when an imported function or intrinsic is used and needs to work
// with waitable registration/unregistration.
struct p3_task_v1 *p3_task_get(void);
// =============================================================================
// Example of a future extension to this API. This is just hypothetical, not
// actually going to be in any header.
// Tasks below would have `version` set to this value.
#define P3_TASK_VERSION2 2
typedef struct p3_task_v2 {
// Must still provide all v1 functionality.
p3_task_v1 v1;
// Some new functionality, but all prior functionality must still be provided.
void (*v2_functionality)(void *p3_task_ptr);
} p3_task_v2;
// Hypothetical v3
#define P3_TASK_VERSION3 3
typedef struct p3_task_v3 {
// Always starts with previous version
p3_task_v2 v2;
void (*v3_functionality)(void *p3_task_ptr);
} p3_task_v3;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment