API for Callback Functions for Network and WtNetwork Structures
Author: Pavel N. Krivitsky

# API for Callback Functions for `Network` and `WtNetwork` Structures

#### Pavel N. Krivitsky

# Overview

## Types of storage and types of term

The callback API provides a way for a `Network` structure to signal precisely when a particular change (e.g., an edge toggle) is about to take place. It is intended to simplify and robustify the management of `u_` functions from the Terms API.

# Formal API definition

## New types

`void OnNetworkEdgeChange(Vertex, Vertex, void *, Network *)` and `void OnWtNetworkEdgeChange(Vertex, Vertex, double, void *, Network *)`, a callback function, compatible with `u_` functions and `Mu_` functions both (since a `void*` can be any pointer).

## New struct elements

### `Network` and `WtNetwork`

`OnNetworkEdgeChange **on_edge_change` and `OnWtNetworkEdgeChange **on_edge_change`: an array of pointers to callback functions.

`void **on_edge_change_payload`: an array of `void` pointers that get passed as the third argument to the corresponding `on_edge_change` function.

`unsigned int n_on_edge_change`: number of callbacks in the above two arrays.

`unsigned int max_on_edge_change`: the amount of space allocated for the above two arrays.

## New functions

`void AddOnNetworkEdgeChange(Network *nwp, OnNetworkEdgeChange u_func, void *payload, unsigned int pos)` and `void AddOnWtNetworkEdgeChange(WtNetwork *nwp, OnWtNetworkEdgeChange u_func, void *payload, unsigned int pos)`: Set a callback `u_func` to be called with argument `payload` whenever an edge in `nwp` is changed. Its position in the list (i.e., the order in which it is called) is set to be `pos` (with large `pos` truncated to indicate the last position).

`void DeleteOnNetworkEdgeChange(Network *nwp, OnNetworkEdgeChange u_func, void *payload)` and `void DeleteOnWtNetworkEdgeChange(WtNetwork *nwp, OnWTNetworkEdgeChange u_func, void *payload)`: Search the list of `nwp`’s callbacks for `u_func` and `payload` and delete the callback when it is found. (If it is not found, an immediate error is raised.)

## NB: Undefined Behaviour Sanitisers

Whereas before, it was possible to define a `u_func` with a specific payload type, e.g., `void u_myterm(Vertex tail, Vertex head, ModelTerm *mtp, Network *nwp)`, this will now trigger a warning by `clang-asan`, since the function signature expected will be different (i.e., `ModelTerm *` vs. `void *`). Terms and proposals therefore wrap their `u` functions, so this should be transparent to the developer, but anyone else using the API should be aware of this.