1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* @file
*
* Chains of named handlers.
*/
#ifndef DRGN_HANDLER_H
#define DRGN_HANDLER_H
#include <stdbool.h>
#include <stdlib.h>
// This should be embedded as the first member in a structure containing the
// handler implementation.
struct drgn_handler {
const char *name;
struct drgn_handler *next;
bool enabled;
// Whether this structure and name need to be freed.
bool free;
};
// This is optimized for frequent drgn_handler_list_for_each_enabled()
// operations; everything else is expected to be rare, so we keep this as small
// as possible.
struct drgn_handler_list {
// All enabled handlers are first, in order, followed by disabled
// handlers in no particular order.
struct drgn_handler *head;
};
// handler->name and handler->free must be initialized.
struct drgn_error *drgn_handler_list_register(struct drgn_handler_list *list,
struct drgn_handler *handler,
size_t enable_index,
const char *what);
struct drgn_error *drgn_handler_list_registered(struct drgn_handler_list *list,
const char ***names_ret,
size_t *count_ret);
struct drgn_error *drgn_handler_list_set_enabled(struct drgn_handler_list *list,
const char * const *names,
size_t count,
const char *what);
struct drgn_error *drgn_handler_list_enabled(struct drgn_handler_list *list,
const char ***names_ret,
size_t *count_ret);
bool drgn_handler_list_disable(struct drgn_handler_list *list,
const char *name);
static inline bool drgn_handler_is_last_enabled(struct drgn_handler *handler)
{
return handler->enabled && (!handler->next || !handler->next->enabled);
}
// Helper to simplify the casting and naming in drgn_handler_list_deinit().
static inline struct drgn_handler *
drgn_handler_free_and_next(struct drgn_handler *handler)
{
struct drgn_handler *next = handler->next;
if (handler->free) {
free((char *)handler->name);
free(handler);
}
return next;
}
// Free all registered handlers, optionally executing a statement for each one.
#define drgn_handler_list_deinit(type, handler, list, ...) do { \
type *handler = (type *)(list)->head; \
while (handler) { \
__VA_ARGS__ \
handler = (type *)drgn_handler_free_and_next((struct drgn_handler *)handler);\
} \
} while (0)
#define drgn_handler_list_for_each_enabled(type, handler, list) \
for (type *handler = (type *)(list)->head; \
handler && ((struct drgn_handler *)handler)->enabled; \
handler = (type *)((struct drgn_handler *)handler)->next)
#endif /* DRGN_HANDLER_H */
|