Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
supervisor.h File Reference
#include <glib.h>
#include <stdint.h>
#include "common/darktable.h"
+ Include dependency graph for supervisor.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  dt_sv_link_t
 
struct  dt_sv_logged_event_t
 

Typedefs

typedef enum dt_sv_op_t dt_sv_op_t
 
typedef struct dt_sv_link_t dt_sv_link_t
 
typedef struct dt_sv_logged_event_t dt_sv_logged_event_t
 

Enumerations

enum  dt_sv_op_t {
  DT_SV_CREATE = 0 ,
  DT_SV_UPDATE ,
  DT_SV_READ ,
  DT_SV_DELETE
}
 

Functions

void dt_supervisor_init (void)
 
void dt_supervisor_cleanup (void)
 
static gboolean dt_supervisor_active (void)
 
void dt_supervisor_set_recording (gboolean on)
 
GPtrArray * dt_supervisor_events_snapshot (void)
 
GPtrArray * dt_supervisor_events_snapshot_since (uint64_t after_seq, uint64_t *out_last_seq)
 
guint dt_supervisor_events_count (void)
 
void dt_supervisor_events_free (GPtrArray *events)
 
void dt_supervisor_events_clear (void)
 
uint64_t dt_supervisor_node_key (int pipe_type, const char *op_name, int multi_priority)
 
uint64_t dt_supervisor_thumbnail_key (int32_t imgid, int mip)
 
uint64_t dt_supervisor_mipmap_key (int32_t imgid, int mip)
 
uint64_t dt_supervisor_image_key (int32_t imgid)
 
void dt_supervisor_history (dt_sv_op_t op, uint64_t param_hash, const char *op_name, int multi_priority, const char *multi_name, int iop_order, int history_index, int32_t imgid, gboolean enabled, const struct dt_iop_module_t *module, const void *params, const struct dt_develop_blend_params_t *blend_params, GList *forms)
 
uint64_t dt_supervisor_form_key (int formid)
 
void dt_supervisor_form (dt_sv_op_t op, const struct dt_masks_form_t *form)
 
void dt_supervisor_node (dt_sv_op_t op, uint64_t node_hash, uint64_t param_hash, uint64_t predecessor_hash, const char *op_name, int multi_priority, int iop_order, int pipe_type, int32_t imgid)
 
void dt_supervisor_cacheline_create (uint64_t hash, uint64_t node_hash, uint64_t param_hash, uint64_t input_hash, const char *op_name, int multi_priority, int iop_order, int pipe_type, int32_t imgid, int roi_w, int roi_h, int devid, size_t size, const char *name)
 
void dt_supervisor_cacheline_read (uint64_t hash, size_t size)
 
void dt_supervisor_cacheline_delete (uint64_t hash, size_t size, int owner_pipe_id, const char *name)
 
void dt_supervisor_rekey (uint64_t old_hash, uint64_t new_hash)
 
void dt_supervisor_backbuf (dt_sv_op_t op, uint64_t hash, uint64_t history_hash, int w, int h, int bpp, int pipe_type, int devid)
 
void dt_supervisor_widget (dt_sv_op_t op, const char *widget_tag, uint64_t consumed_hash, int pipe_type, int32_t imgid)
 
void dt_supervisor_thumbnail (dt_sv_op_t op, int32_t imgid, int width, int height, int mip, gboolean success)
 
void dt_supervisor_mipmap (dt_sv_op_t op, int32_t imgid, int mip)
 
void dt_supervisor_image (dt_sv_op_t op, int32_t imgid, const struct dt_image_t *img)
 
void dt_supervisor_cache_wait (dt_sv_op_t op, uint64_t request_id, uint64_t awaited_hash, const char *owner_tag, const char *op_name, int multi_priority, int pipe_type, int32_t imgid, gboolean request_emitted, const char *note)
 
gchar * dt_supervisor_describe (uint64_t hash)
 

Variables

gint dt_supervisor_recording
 

Typedef Documentation

◆ dt_sv_link_t

typedef struct dt_sv_link_t dt_sv_link_t

One retained event, as exposed to the GUI by dt_supervisor_events_snapshot(). links holds the resolved edge hashes (params/input/node/consumes/rekey) so the GUI can make every id clickable and navigate to its declaration.

◆ dt_sv_logged_event_t

◆ dt_sv_op_t

typedef enum dt_sv_op_t dt_sv_op_t

High-level event supervisor.

Ansel is deeply asynchronous: GUI, history and pixelpipe live in different threads and identify their objects by content-addressed hashes. The supervisor links those objects through the hashes they already carry and emits one line of newline-delimited JSON (NDJSON) per CRUD event, with the links already resolved.

Registry as memory

Every tracked object registers itself by its own hash, and declares (by hash) the object it consumes and the parameter identity it derives from. Entries live in the registry until the session ends — they are NEVER removed. A delete event does not drop the entry; it flips an alive flag to FALSE. This turns the registry into a memory: a CREATE or READ landing on a hash whose entry is alive == FALSE is a reuse-after-delete, flagged "resurrected": true in the emitted record. Such use-after-free patterns are otherwise invisible.

Two hash families do all the linking (see reorganisation.md):

  • parameter identity: history_item.hash == module.hash == piece.hash;
  • output identity: piece.global_hash == cache_entry.hash == backbuf.hash. Pipeline nodes are topology objects, keyed by a stable synthetic key (pipe, module instance) computed by dt_supervisor_node_key().

Thread safety

The registry is guarded by ONE supervisor mutex. Emitters value-copy the fields they are passed; the registry never holds a pointer to a live foreign object and resolves at most two edge hops, so it never walks across lock domains. The supervisor mutex is always taken as a leaf (never while another supervisor call is in flight); taking it under the pixelpipe-cache lock at a read chokepoint is safe because the ordering is never inverted.

Everything is gated by -d supervisor (DT_DEBUG_SUPERVISOR). When off, dt_supervisor_active() short-circuits each call site to one predicted-false branch. See doc/supervisor.md for the schema and the jq recipes.

Enumeration Type Documentation

◆ dt_sv_op_t

enum dt_sv_op_t

High-level event supervisor.

Ansel is deeply asynchronous: GUI, history and pixelpipe live in different threads and identify their objects by content-addressed hashes. The supervisor links those objects through the hashes they already carry and emits one line of newline-delimited JSON (NDJSON) per CRUD event, with the links already resolved.

Registry as memory

Every tracked object registers itself by its own hash, and declares (by hash) the object it consumes and the parameter identity it derives from. Entries live in the registry until the session ends — they are NEVER removed. A delete event does not drop the entry; it flips an alive flag to FALSE. This turns the registry into a memory: a CREATE or READ landing on a hash whose entry is alive == FALSE is a reuse-after-delete, flagged "resurrected": true in the emitted record. Such use-after-free patterns are otherwise invisible.

Two hash families do all the linking (see reorganisation.md):

  • parameter identity: history_item.hash == module.hash == piece.hash;
  • output identity: piece.global_hash == cache_entry.hash == backbuf.hash. Pipeline nodes are topology objects, keyed by a stable synthetic key (pipe, module instance) computed by dt_supervisor_node_key().

Thread safety

The registry is guarded by ONE supervisor mutex. Emitters value-copy the fields they are passed; the registry never holds a pointer to a live foreign object and resolves at most two edge hops, so it never walks across lock domains. The supervisor mutex is always taken as a leaf (never while another supervisor call is in flight); taking it under the pixelpipe-cache lock at a read chokepoint is safe because the ordering is never inverted.

Everything is gated by -d supervisor (DT_DEBUG_SUPERVISOR). When off, dt_supervisor_active() short-circuits each call site to one predicted-false branch. See doc/supervisor.md for the schema and the jq recipes.

Enumerator
DT_SV_CREATE 
DT_SV_UPDATE 
DT_SV_READ 
DT_SV_DELETE 

Definition at line 75 of file supervisor.h.

Function Documentation

◆ dt_supervisor_active()

static gboolean dt_supervisor_active ( void  )
inlinestatic

◆ dt_supervisor_backbuf()

void dt_supervisor_backbuf ( dt_sv_op_t  op,
uint64_t  hash,
uint64_t  history_hash,
int  w,
int  h,
int  bpp,
int  pipe_type,
int  devid 
)

◆ dt_supervisor_cache_wait()

void dt_supervisor_cache_wait ( dt_sv_op_t  op,
uint64_t  request_id,
uint64_t  awaited_hash,
const char *  owner_tag,
const char *  op_name,
int  multi_priority,
int  pipe_type,
int32_t  imgid,
gboolean  request_emitted,
const char *  note 
)

Cache-wait request event — one queued GUI fetch through the cache-wait manager (dev_pixelpipe.c). Keyed by a synthetic key over request_id, so the queue / serve / cancel of one request fold onto a single object and successive requests from the same consumer stay distinct.

The event carries an awaits edge to the cacheline hash the GUI is blocked on: clicking it walks cache-wait -> awaits -> cacheline. If no cacheline was ever published under that hash, the edge degrades to a raw awaits_hash — that missing target is the fingerprint of the "order to grab a cacheline is never processed" failure (the pipe published a different hash than the GUI awaits, so CACHELINE_READY never matches the pending record).

Parameters
opCREATE at queue, READ on a deduped re-poll (a repeat peek that found the same wait in flight and suppressed a new CACHE_REQUEST), DELETE at serve or cancel.
request_idthe wait's monotonic request id (identity).
awaited_hashthe cacheline hash being waited on.
owner_tagconsumer label (e.g. "color-picker-input").
op_nametarget module op (NULL for a backbuf request).
request_emittedTRUE when this event also (re)emitted a CACHE_REQUEST to the pipe; FALSE on a deduped re-poll.
noteoptional free-text qualifier ("served", "cancelled: …").

Definition at line 1013 of file supervisor.c.

References _cache_wait_key(), _emit_line(), _entry_get_locked(), _envelope(), _hash_is_set(), _module_label(), _resolve_locked(), _set_hash_member(), _sv, _touch_alive_locked(), dt_sv_entry_t::alive, dt_sv_entry_t::awaits_hash, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), dt_supervisor_active(), DT_SV_F_CACHEWAIT, dt_sv_entry_t::facets, dt_sv_entry_t::imgid, key, dt_sv_entry_t::multi_priority, dt_sv_entry_t::op_name, dt_sv_entry_t::owner_tag, dt_sv_entry_t::pipe_type, dt_sv_entry_t::request_emitted, and dt_sv_entry_t::request_id.

Referenced by _dt_dev_pixelpipe_cache_wait_ready_callback(), dt_dev_pixelpipe_cache_peek_gui(), and dt_dev_pixelpipe_cache_wait_cleanup().

◆ dt_supervisor_cacheline_create()

void dt_supervisor_cacheline_create ( uint64_t  hash,
uint64_t  node_hash,
uint64_t  param_hash,
uint64_t  input_hash,
const char *  op_name,
int  multi_priority,
int  iop_order,
int  pipe_type,
int32_t  imgid,
int  roi_w,
int  roi_h,
int  devid,
size_t  size,
const char *  name 
)

Cacheline output created at runtime publish — keyed by the produced output hash (piece->global_hash). Carries the full linkage so later READ/DELETE events (which only know the hash) resolve against the registry memory.

Parameters
node_hashproducing topology node (dt_supervisor_node_key()).
param_hashpiece->hash, links to the history/module identity.
input_hashprevious enabled piece's output hash, or INVALID/0.
devidOpenCL device id, or < 0 for CPU.

Definition at line 891 of file supervisor.c.

References _device_string(), _emit_line(), _entry_get_locked(), _envelope(), _hash_is_set(), _module_label(), _resolve_locked(), _sv, _touch_alive_locked(), dt_sv_entry_t::alive, dt_sv_entry_t::cl_name, dt_sv_entry_t::devid, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), dt_supervisor_active(), DT_SV_CREATE, DT_SV_F_CACHE, dt_sv_entry_t::facets, dt_sv_entry_t::imgid, dt_sv_entry_t::input_hash, dt_sv_entry_t::iop_order, dt_sv_entry_t::multi_priority, name, dt_sv_entry_t::node_hash, dt_sv_entry_t::op_name, dt_sv_entry_t::param_hash, dt_sv_entry_t::pipe_type, dt_sv_entry_t::roi_h, dt_sv_entry_t::roi_w, size, and dt_sv_entry_t::size.

Referenced by dt_dev_pixelpipe_process_rec(), dt_develop_blend_process(), and dt_develop_blend_process_cl().

◆ dt_supervisor_cacheline_delete()

◆ dt_supervisor_cacheline_read()

◆ dt_supervisor_cleanup()

void dt_supervisor_cleanup ( void  )

◆ dt_supervisor_describe()

gchar * dt_supervisor_describe ( uint64_t  hash)

◆ dt_supervisor_events_clear()

void dt_supervisor_events_clear ( void  )

Definition at line 310 of file supervisor.c.

References _logged_event_free(), _sv, dt_pthread_mutex_lock(), and dt_pthread_mutex_unlock().

Referenced by _on_clear().

◆ dt_supervisor_events_count()

guint dt_supervisor_events_count ( void  )

Definition at line 1508 of file supervisor.c.

References _sv, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), and n.

Referenced by _update_count().

◆ dt_supervisor_events_free()

void dt_supervisor_events_free ( GPtrArray *  events)

Definition at line 1517 of file supervisor.c.

References TRUE.

Referenced by _grouped_catch_up(), _poll(), and _run_search().

◆ dt_supervisor_events_snapshot()

GPtrArray * dt_supervisor_events_snapshot ( void  )

◆ dt_supervisor_events_snapshot_since()

GPtrArray * dt_supervisor_events_snapshot_since ( uint64_t  after_seq,
uint64_t out_last_seq 
)

◆ dt_supervisor_form()

void dt_supervisor_form ( dt_sv_op_t  op,
const struct dt_masks_form_t form 
)

Mask form lifecycle event — keyed by dt_supervisor_form_key(form->formid). create at allocation (dt_masks_create), update when a history snapshot carries the form (name/members filled in). Carries id, name, type and, for groups, the member form ids.

◆ dt_supervisor_form_key()

uint64_t dt_supervisor_form_key ( int  formid)

Definition at line 209 of file supervisor.c.

References _form_key().

◆ dt_supervisor_history()

void dt_supervisor_history ( dt_sv_op_t  op,
uint64_t  param_hash,
const char *  op_name,
int  multi_priority,
const char *  multi_name,
int  iop_order,
int  history_index,
int32_t  imgid,
gboolean  enabled,
const struct dt_iop_module_t module,
const void params,
const struct dt_develop_blend_params_t blend_params,
GList *  forms 
)

History item event — keyed by its parameter hash (== module hash == node param hash), the join target nodes/cachelines resolve their params edge to. DELETE flips alive to FALSE without dropping the entry.

◆ dt_supervisor_image()

void dt_supervisor_image ( dt_sv_op_t  op,
int32_t  imgid,
const struct dt_image_t img 
)

Image cache object event — the canonical dt_image_t for an imgid, keyed by dt_supervisor_image_key(). create when the entry is loaded from the database, delete on eviction. Its properties are its dt_image_t.

◆ dt_supervisor_image_key()

uint64_t dt_supervisor_image_key ( int32_t  imgid)

Definition at line 191 of file supervisor.c.

References _image_key().

Referenced by _rebuild_memory().

◆ dt_supervisor_init()

void dt_supervisor_init ( void  )

Definition at line 283 of file supervisor.c.

References _sv, dt_pthread_mutex_init(), and TRUE.

Referenced by dt_init().

◆ dt_supervisor_mipmap()

void dt_supervisor_mipmap ( dt_sv_op_t  op,
int32_t  imgid,
int  mip 
)

◆ dt_supervisor_mipmap_key()

uint64_t dt_supervisor_mipmap_key ( int32_t  imgid,
int  mip 
)

Definition at line 181 of file supervisor.c.

References _mipmap_key().

Referenced by _rebuild_memory().

◆ dt_supervisor_node()

void dt_supervisor_node ( dt_sv_op_t  op,
uint64_t  node_hash,
uint64_t  param_hash,
uint64_t  predecessor_hash,
const char *  op_name,
int  multi_priority,
int  iop_order,
int  pipe_type,
int32_t  imgid 
)

Pipeline topology node event — keyed by dt_supervisor_node_key().

  • CREATE when the pipe builds its nodes (topology), with param_hash INVALID;
  • UPDATE when the node is synchronized with a history entry in dt_dev_pixelpipe_change(): param_hash is the committed piece->hash, which ties the node (and the cachelines it produces) to its history item;
  • DELETE when the nodes are torn down. Not emitted from the processing recursion.

Definition at line 856 of file supervisor.c.

References _emit_line(), _entry_get_locked(), _envelope(), _hash_is_set(), _module_label(), _resolve_locked(), _sv, _touch_alive_locked(), dt_sv_entry_t::alive, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), dt_supervisor_active(), DT_SV_F_NODE, dt_sv_entry_t::facets, dt_sv_entry_t::imgid, dt_sv_entry_t::iop_order, dt_sv_entry_t::multi_priority, dt_sv_entry_t::op_name, dt_sv_entry_t::param_hash, dt_sv_entry_t::pipe_type, and dt_sv_entry_t::pred_hash.

Referenced by _sync_pipe_nodes_from_history(), _sync_pipe_nodes_from_history_from_node(), dt_dev_pixelpipe_cleanup_nodes(), and dt_dev_pixelpipe_create_nodes().

◆ dt_supervisor_node_key()

uint64_t dt_supervisor_node_key ( int  pipe_type,
const char *  op_name,
int  multi_priority 
)

Stable identity of a pipeline topology node: a function of the pipe type and the module instance (op + multi_priority), independent of parameters or ROI. The producer (create_nodes) and the consumers (a cacheline declaring its producer) call this to agree on the same key. Never returns INVALID.

Definition at line 161 of file supervisor.c.

References _fnv1a().

Referenced by _sync_pipe_nodes_from_history(), _sync_pipe_nodes_from_history_from_node(), dt_dev_pixelpipe_cache_peek_gui(), dt_dev_pixelpipe_cleanup_nodes(), dt_dev_pixelpipe_create_nodes(), dt_dev_pixelpipe_process(), dt_dev_pixelpipe_process_rec(), dt_develop_blend_process(), and dt_develop_blend_process_cl().

◆ dt_supervisor_rekey()

void dt_supervisor_rekey ( uint64_t  old_hash,
uint64_t  new_hash 
)

Rekey: an object's hash changed in place (a pipeline cacheline rekeyed for reuse, or a history item overwritten so its parameter hash changed). Modelled as "delete old hash + add new hash": the old entry is marked alive == FALSE (emitting a delete with rekeyed_to), and the new entry inherits the old metadata and is created/revived (emitting a create with rekeyed_from). Domain-agnostic; the domain is derived from the old entry's facets.

Definition at line 1079 of file supervisor.c.

References _emit_line(), _entry_get_locked(), _hash_is_set(), _rekey_record(), _sv, dt_sv_entry_t::alive, dt_sv_entry_t::bb_bpp, dt_sv_entry_t::bb_h, dt_sv_entry_t::bb_w, dt_sv_entry_t::cl_name, dt_sv_entry_t::devid, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), dt_supervisor_active(), DT_SV_CREATE, DT_SV_DELETE, dt_sv_entry_t::enabled, dt_sv_entry_t::facets, FALSE, dt_sv_entry_t::history_hash, dt_sv_entry_t::history_index, dt_sv_entry_t::imgid, dt_sv_entry_t::input_hash, dt_sv_entry_t::iop_order, dt_sv_entry_t::multi_name, dt_sv_entry_t::multi_priority, dt_sv_entry_t::node_hash, dt_sv_entry_t::op_name, dt_sv_entry_t::param_hash, dt_sv_entry_t::pipe_type, dt_sv_entry_t::roi_h, dt_sv_entry_t::roi_w, dt_sv_entry_t::size, and TRUE.

Referenced by _cache_try_rekey_reuse_locked(), dt_dev_add_history_item_ext(), and dt_dev_pixelpipe_cache_rekey().

◆ dt_supervisor_set_recording()

void dt_supervisor_set_recording ( gboolean  on)

Definition at line 305 of file supervisor.c.

References dt_supervisor_recording.

Referenced by _on_destroy(), _on_record_toggled(), and dt_gui_supervisor_window_show().

◆ dt_supervisor_thumbnail()

void dt_supervisor_thumbnail ( dt_sv_op_t  op,
int32_t  imgid,
int  width,
int  height,
int  mip,
gboolean  success 
)

Thumbnail generation event — a thumbnail widget fetching its mipmap (and the pipeline render behind it, which surfaces through the generic node/cacheline/ backbuf events of the thumbnail pipe). Keyed by a synthetic (imgid, mip) key.

Definition at line 1195 of file supervisor.c.

References _emit_line(), _entry_get_locked(), _envelope(), _mipmap_key(), _set_hash_member(), _sv, _thumb_key(), _touch_alive_locked(), dt_sv_entry_t::alive, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), dt_supervisor_active(), DT_SV_F_THUMB, dt_sv_entry_t::facets, height, dt_sv_entry_t::img_filename, dt_sv_entry_t::imgid, key, dt_sv_entry_t::mip, dt_sv_entry_t::roi_h, dt_sv_entry_t::roi_w, size, dt_sv_entry_t::thumb_success, and width.

Referenced by _view_image_get_surface_internal().

◆ dt_supervisor_thumbnail_key()

uint64_t dt_supervisor_thumbnail_key ( int32_t  imgid,
int  mip 
)

Definition at line 171 of file supervisor.c.

References _thumb_key().

◆ dt_supervisor_widget()

void dt_supervisor_widget ( dt_sv_op_t  op,
const char *  widget_tag,
uint64_t  consumed_hash,
int  pipe_type,
int32_t  imgid 
)

Widget paint event — declares the backbuf/cacheline hash the widget consumed. The module/history narrative is resolved from the registry memory.

Definition at line 1173 of file supervisor.c.

References _emit_line(), _envelope(), _resolve_locked(), _sv, dt_sv_entry_t::alive, dt_pthread_mutex_lock(), dt_pthread_mutex_unlock(), dt_supervisor_active(), DT_SV_F_WIDGET, dt_sv_entry_t::facets, FALSE, dt_sv_entry_t::param_hash, and TRUE.

Referenced by dt_dev_lock_pipe_surface().

Variable Documentation

◆ dt_supervisor_recording

gint dt_supervisor_recording
extern

Definition at line 112 of file supervisor.c.

Referenced by _emit_line(), dt_supervisor_active(), and dt_supervisor_set_recording().