]>
Commit | Line | Data |
---|---|---|
2a6a7a65 DL |
1 | .. highlight:: c |
2 | ||
3 | Hooks | |
4 | ===== | |
5 | ||
6 | Libfrr provides type-safe subscribable hook points where other pieces of | |
7 | code can add one or more callback functions. "type-safe" in this case | |
8 | applies to the function pointers used for subscriptions. The | |
56f0bea7 | 9 | implementations checks (at compile-time) whether a callback to be added has |
2a6a7a65 DL |
10 | the appropriate function signature (parameters) for the hook. |
11 | ||
12 | Example: | |
13 | ||
14 | .. code-block:: c | |
75ca3b11 | 15 | :caption: mydaemon.h |
2a6a7a65 | 16 | |
75ca3b11 QY |
17 | #include "hook.h" |
18 | DECLARE_HOOK(some_update_event, (struct eventinfo *info), (info)) | |
2a6a7a65 DL |
19 | |
20 | .. code-block:: c | |
75ca3b11 | 21 | :caption: mydaemon.c |
2a6a7a65 | 22 | |
75ca3b11 QY |
23 | #include "mydaemon.h" |
24 | DEFINE_HOOK(some_update_event, (struct eventinfo *info), (info)) | |
25 | ... | |
26 | hook_call(some_update_event, info); | |
2a6a7a65 DL |
27 | |
28 | .. code-block:: c | |
75ca3b11 | 29 | :caption: mymodule.c |
2a6a7a65 | 30 | |
75ca3b11 QY |
31 | #include "mydaemon.h" |
32 | static int event_handler(struct eventinfo *info); | |
33 | ... | |
34 | hook_register(some_update_event, event_handler); | |
2a6a7a65 DL |
35 | |
36 | Do not use parameter names starting with "hook", these can collide with | |
37 | names used by the hook code itself. | |
38 | ||
39 | ||
40 | Return values | |
41 | ------------- | |
42 | ||
43 | Callbacks to be placed on hooks always return "int" for now; hook_call will | |
44 | sum up the return values from each called function. (The default is 0 if no | |
45 | callbacks are registered.) | |
46 | ||
47 | There are no pre-defined semantics for the value, in most cases it is | |
48 | ignored. For success/failure indication, 0 should be success, and | |
49 | handlers should make sure to only return 0 or 1 (not -1 or other values). | |
50 | ||
51 | There is no built-in way to abort executing a chain after a failure of one | |
52 | of the callbacks. If this is needed, the hook can use an extra | |
53 | ``bool *aborted`` argument. | |
54 | ||
55 | ||
56 | Priorities | |
57 | ---------- | |
58 | ||
59 | Hooks support a "priority" value for ordering registered calls | |
60 | relative to each other. The priority is a signed integer where lower | |
61 | values are called earlier. There are also "Koohs", which is hooks with | |
62 | reverse priority ordering (for cleanup/deinit hooks, so you can use the | |
63 | same priority value). | |
64 | ||
65 | Recommended priority value ranges are: | |
66 | ||
67 | ======================== =================================================== | |
68 | Range Usage | |
69 | ------------------------ --------------------------------------------------- | |
70 | -999 ... 0 ... 999 main executable / daemon, or library | |
71 | ||
72 | -1999 ... -1000 modules registering calls that should run before | |
73 | the daemon's bits | |
74 | ||
75 | 1000 ... 1999 modules' calls that should run after daemon's | |
76 | (includes default value: 1000) | |
77 | ======================== =================================================== | |
78 | ||
79 | Note: the default value is 1000, based on the following 2 expectations: | |
80 | ||
81 | - most hook_register() usage will be in loadable modules | |
82 | - usage of hook_register() in the daemon itself may need relative ordering | |
83 | to itself, making an explicit value the expected case | |
84 | ||
85 | The priority value is passed as extra argument on hook_register_prio() / | |
86 | hook_register_arg_prio(). Whether a hook runs in reverse is determined | |
87 | solely by the code defining / calling the hook. (DECLARE_KOOH is actually | |
88 | the same thing as DECLARE_HOOK, it's just there to make it obvious.) | |
89 | ||
90 | ||
91 | Definition | |
92 | ---------- | |
93 | ||
94 | .. c:macro:: DECLARE_HOOK(name, arglist, passlist) | |
95 | .. c:macro:: DECLARE_KOOH(name, arglist, passlist) | |
96 | ||
97 | :param name: Name of the hook to be defined | |
98 | :param arglist: Function definition style parameter list in braces. | |
99 | :param passlist: List of the same parameters without their types. | |
100 | ||
101 | Note: the second and third macro args must be the hook function's | |
102 | parameter list, with the same names for each parameter. The second | |
103 | macro arg is with types (used for defining things), the third arg is | |
104 | just the names (used for passing along parameters). | |
105 | ||
106 | This macro must be placed in a header file; this header file must be | |
107 | included to register a callback on the hook. | |
108 | ||
109 | Examples: | |
110 | ||
111 | .. code-block:: c | |
112 | ||
113 | DECLARE_HOOK(foo, (), ()) | |
114 | DECLARE_HOOK(bar, (int arg), (arg)) | |
115 | DECLARE_HOOK(baz, (const void *x, in_addr_t y), (x, y)) | |
116 | ||
117 | .. c:macro:: DEFINE_HOOK(name, arglist, passlist) | |
118 | ||
119 | Implements an hook. Each ``DECLARE_HOOK`` must have be accompanied by | |
120 | exactly one ``DEFINE_HOOK``, which needs to be placed in a source file. | |
121 | **The hook can only be called from this source file.** This is intentional | |
122 | to avoid overloading and/or misusing hooks for distinct purposes. | |
123 | ||
124 | The compiled source file will include a global symbol with the name of the | |
125 | hook prefixed by `_hook_`. Trying to register a callback for a hook that | |
126 | doesn't exist will therefore result in a linker error, or a module | |
127 | load-time error for dynamic modules. | |
128 | ||
129 | .. c:macro:: DEFINE_KOOH(name, arglist, passlist) | |
130 | ||
131 | Same as ``DEFINE_HOOK``, but the sense of priorities / order of callbacks | |
132 | is reversed. This should be used for cleanup hooks. | |
133 | ||
134 | .. c:function:: int hook_call(name, ...) | |
135 | ||
136 | Calls the specified named hook. Parameters to the hook are passed right | |
137 | after the hook name, e.g.: | |
138 | ||
139 | .. code-block:: c | |
140 | ||
141 | hook_call(foo); | |
142 | hook_call(bar, 0); | |
143 | hook_call(baz, NULL, INADDR_ANY); | |
144 | ||
145 | Returns the sum of return values from all callbacks. The ``DEFINE_HOOK`` | |
146 | statement for the hook must be placed in the file before any ``hook_call`` | |
147 | use of the hook. | |
148 | ||
149 | ||
150 | Callback registration | |
151 | --------------------- | |
152 | ||
153 | .. c:function:: void hook_register(name, int (*callback)(...)) | |
154 | .. c:function:: void hook_register_prio(name, int priority, int (*callback)(...)) | |
155 | .. c:function:: void hook_register_arg(name, int (*callback)(void *arg, ...), void *arg) | |
156 | .. c:function:: void hook_register_arg_prio(name, int priority, int (*callback)(void *arg, ...), void *arg) | |
157 | ||
158 | Register a callback with an hook. If the caller needs to pass an extra | |
159 | argument to the callback, the _arg variant can be used and the extra | |
160 | parameter will be passed as first argument to the callback. There is no | |
161 | typechecking for this argument. | |
162 | ||
163 | The priority value is used as described above. The variants without a | |
164 | priority parameter use 1000 as priority value. | |
165 | ||
166 | .. c:function:: void hook_unregister(name, int (*callback)(...)) | |
167 | .. c:function:: void hook_unregister_arg(name, int (*callback)(void *arg, ...), void *arg) | |
168 | ||
169 | Removes a previously registered callback from a hook. Note that there | |
170 | is no _prio variant of these calls. The priority value is only used during | |
171 | registration. |