diff --git a/include/haproxy/list-t.h b/include/haproxy/list-t.h index dd8493eed..914e5a17b 100644 --- a/include/haproxy/list-t.h +++ b/include/haproxy/list-t.h @@ -57,6 +57,17 @@ struct bref { struct list *ref; /* pointer to the target's list entry */ }; +/* Similar to bref. Used to reference an element which is tracking a dynamic + * target. The main advantage over bref is that when target is freed, each + * elements pointers are automatically updated to the next entry or NULL if + * target was the last one. + */ +struct watcher { + struct mt_list el; /* attach point into target list */ + void **pptr; /* pointer to element which points to target */ + size_t off; /* offset into target type for mtlist storage of watcher */ +}; + /* a word list is a generic list with a pointer to a string in each element. */ struct wordlist { struct list list; diff --git a/include/haproxy/list.h b/include/haproxy/list.h index 584148859..ff203147c 100644 --- a/include/haproxy/list.h +++ b/include/haproxy/list.h @@ -260,4 +260,46 @@ static __inline struct mt_list *list_to_mt_list(struct list *list) } +/* Init a watcher entry to track targets. is the pointer to the + * target pointer which will be updated via watcher_attach/detach operations. + * is the offset to access the target mt_list attach point for the + * watcher entry. + */ +static __inline void watcher_init(struct watcher *w, void *pptr, size_t attach_off) +{ + MT_LIST_INIT(&w->el); + w->pptr = pptr; + w->off = attach_off; +} + +/* Tracks via watcher. Invalid if is already attached. */ +static __inline void watcher_attach(struct watcher *w, void *target) +{ + struct mt_list *list = target + w->off; + + BUG_ON_HOT(MT_LIST_INLIST(&w->el)); + + *w->pptr = target; + if (target) + MT_LIST_APPEND(list, &w->el); +} + +/* Untracks target via watcher. Invalid if is not attached first. */ +static __inline void watcher_detach(struct watcher *w) +{ + BUG_ON_HOT(!MT_LIST_INLIST(&w->el)); + *w->pptr = NULL; + MT_LIST_DELETE(&w->el); +} + +/* Equivalent to a detach then attach on via watcher. Returns + * as a convenience to use this function as increment in a for-loop. + */ +static __inline void *watcher_next(struct watcher *w, void *target) +{ + watcher_detach(w); + watcher_attach(w, target); + return target; +} + #endif /* _HAPROXY_LIST_H */