Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
optional_api.h
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2008-2013, Digium, Inc.
5 *
6 * Kevin P. Fleming <kpfleming@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19#ifndef __ASTERISK_OPTIONAL_API_H
20#define __ASTERISK_OPTIONAL_API_H
21
22/*!
23 * \file
24 * \brief Optional API function macros
25 *
26 * Some Asterisk API functions are provided by loadable modules, thus,
27 * they may or may not be available at run time depending on whether the
28 * providing module has been loaded or not. In addition, there are some
29 * modules that are consumers of these APIs that *optionally* use them; they
30 * have only a part of their functionality dependent on the APIs, and can
31 * provide the remainder even if the APIs are not available.
32 *
33 * An example can be found in agi.h:
34 *
35 * \code
36 * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
37 * { return AST_OPTIONAL_API_UNAVAILABLE; });
38 * \endcode
39 *
40 * This defines the 'ast_agi_register' function as an optional API; if a
41 * consumer of this API is loaded when there is no provider of it, then
42 * calling this function will actually call the hidden stub, and return
43 * the value AST_OPTIONAL_API_UNAVAILABLE. This allows the consumer to
44 * safely know that the API is not available, and to avoid using any
45 * other APIs from the not-present provider.
46 *
47 * In addition to this declaration in the header file, the actual definition of
48 * the API function must use the AST_OPTIONAL_API_NAME macro to (possibly)
49 * modify the real name of the API function, depending on the specific
50 * implementation requirements. The corresponding example from res_agi.c:
51 *
52 * \code
53 * int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
54 * {
55 * ...
56 * }
57 * \endcode
58 *
59 * In the module providing the API, the AST_OPTIONAL_API macro must
60 * be informed that it should not build the hidden stub function or
61 * apply special aliases to the function prototype; this can be done
62 * by defining AST_API_MODULE just before including the header file
63 * containing the AST_OPTIONAL_API macro calls.
64 */
65
66/*!
67 * \brief A common value for optional API stub functions to return
68 *
69 * This value is defined as INT_MIN, the minimum value for an integer
70 * (maximum negative value), which can be used by any optional API
71 * functions that return a signed integer value and would not be
72 * able to return such a value under normal circumstances.
73 */
74#define AST_OPTIONAL_API_UNAVAILABLE INT_MIN
75
76/*!
77 * \def AST_OPTIONAL_API_NAME(name)
78 * \brief Expands to the name of the implementation function.
79 */
80
81/*!
82 * \def AST_OPTIONAL_API(result, name, proto, stub)
83 * \brief Declare an optional API function
84 *
85 * \param result The type of result the function returns
86 * \param name The name of the function
87 * \param proto The prototype (arguments) of the function
88 * \param stub The code block that will be used by the hidden stub when needed
89 *
90 * Example usage:
91 * \code
92 * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
93 * { return AST_OPTIONAL_API_UNAVAILABLE; });
94 * \endcode
95 */
96
97/*!
98 * \def AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)
99 * \brief Declare an optional API function with compiler attributes
100 *
101 * \param result The type of result the function returns
102 * \param attr Any compiler attributes to be applied to the function (without the __attribute__ wrapper)
103 * \param name The name of the function
104 * \param proto The prototype (arguments) of the function
105 * \param stub The code block that will be used by the hidden stub when needed
106 */
107
108#if defined(OPTIONAL_API)
109
110/*!
111 * \internal
112 * \brief Function pointer to an optional API function.
113 *
114 * Functions that are declared as optional may have any signature they want;
115 * they are cast to this type as needed. We don't use a \c void pointer, because
116 * technically data and function pointers are incompatible.
117 *
118 * \note
119 * The may_alias attribute is to avoid type punning/strict aliasing warnings
120 * with older GCC's.
121 */
122typedef void (*ast_optional_fn)(void) attribute_may_alias;
123
124/*!
125 * \internal
126 * \brief Provide an implementation of an optional API.
127 *
128 * Any declared usages of this function are linked.
129 *
130 * \param symname Name of the provided function.
131 * \param impl Function pointer to the implementation function.
132 */
133void ast_optional_api_provide(const char *symname, ast_optional_fn impl);
134
135/*!
136 * \internal
137 * \brief Remove an implementation of an optional API.
138 *
139 * Any declared usages of this function are unlinked.
140 *
141 * \param symname Name of the provided function.
142 * \param impl Function pointer to the implementation function.
143 */
144void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl);
145
146/*!
147 * \internal
148 * \brief Define a usage of an optional API.
149 *
150 * If the API has been provided, it will be linked into \a optional_ref.
151 * Otherwise, it will be linked to \a stub until an implementation is provided.
152 *
153 * \param symname Name of the function to use.
154 * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
155 * \param stub Stub function to link to when impl is not available.
156 * \param module Name of the module requesting the API.
157 */
158void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
159 ast_optional_fn stub, const char *module);
160
161/*!
162 * \internal
163 * \brief Remove a usage of an optional API.
164 *
165 * The \a optional_ref will be linked to the \a stub provided at use time,
166 * will no longer be updated if the API is provided/removed.
167 *
168 * \param symname Name of the function to use.
169 * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
170 * \param module Name of the module requesting the API.
171 */
172void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,
173 const char *module);
174
175#define AST_OPTIONAL_API_NAME(name) __##name
176
177#define AST_OPTIONAL_API_INIT_IMPL(name) \
178 static void __attribute__((constructor)) __init__##name##_impl(void) { \
179 ast_optional_api_provide(#name, \
180 (ast_optional_fn)AST_OPTIONAL_API_NAME(name)); \
181 } \
182 static void __attribute__((destructor)) __dtor__##name##_impl(void) { \
183 ast_optional_api_unprovide(#name, \
184 (ast_optional_fn)AST_OPTIONAL_API_NAME(name)); \
185 }
186
187#define AST_OPTIONAL_API_INIT_USER(name) \
188 static void __attribute__((constructor)) __init__##name(void) { \
189 ast_optional_api_use(#name, (ast_optional_fn *)&name, \
190 (ast_optional_fn)__stub__##name, \
191 AST_MODULE); \
192 } \
193 static void __attribute__((destructor)) __dtor__##name(void) { \
194 ast_optional_api_unuse(#name, (ast_optional_fn *)&name, \
195 AST_MODULE); \
196 }
197
198#define AST_OPTIONAL_API_IMPL(result, name, proto, stub) \
199 result AST_OPTIONAL_API_NAME(name) proto; \
200 static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
201 name = AST_OPTIONAL_API_NAME(name); \
202 AST_OPTIONAL_API_INIT_IMPL(name)
203
204#define AST_OPTIONAL_API_USER(result, name, proto, stub) \
205 static result __stub__##name proto stub; \
206 static attribute_unused \
207 typeof(__stub__##name) * name; \
208 AST_OPTIONAL_API_INIT_USER(name)
209
210
211/* AST_OPTIONAL_API_ATTR */
212#define AST_OPTIONAL_API_ATTR_IMPL(result, attr, name, proto, stub) \
213 result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
214 static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
215 name = AST_OPTIONAL_API_NAME(name); \
216 AST_OPTIONAL_API_INIT_IMPL(name)
217
218#define AST_OPTIONAL_API_ATTR_USER(result, attr, name, proto, stub) \
219 static __attribute__((attr)) result __stub__##name proto stub; \
220 static attribute_unused __attribute__((attr)) \
221 typeof(__stub__##name) * name; \
222 AST_OPTIONAL_API_INIT_USER(name)
223
224#else /* defined(OPTIONAL_API) */
225
226/* Non-optional API */
227
228#define AST_OPTIONAL_API_NAME(name) name
229
230#define AST_OPTIONAL_API(result, name, proto, stub) \
231 result AST_OPTIONAL_API_NAME(name) proto
232
233#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
234 result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto
235
236#endif /* defined(OPTIONAL_API) */
237
238#endif /* __ASTERISK_OPTIONAL_API_H */
239
240/*
241 * Some Asterisk sources are both consumer and provider of optional API's. The
242 * following definitons are intentionally outside the include protected portion
243 * of this header so AST_OPTIONAL_API and AST_OPTIONAL_API_ATTR can be redefined
244 * each time the header is included. This also ensures that AST_API_MODULE is
245 * undefined after every include of this header.
246 */
247#if defined(OPTIONAL_API)
248
249#undef AST_OPTIONAL_API
250#undef AST_OPTIONAL_API_ATTR
251
252#if defined(AST_API_MODULE)
253
254#define AST_OPTIONAL_API(result, name, proto, stub) \
255 AST_OPTIONAL_API_IMPL(result, name, proto, stub)
256
257#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
258 AST_OPTIONAL_API_ATTR_IMPL(result, attr, name, proto, stub)
259
260#else
261
262#define AST_OPTIONAL_API(result, name, proto, stub) \
263 AST_OPTIONAL_API_USER(result, name, proto, stub)
264
265#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
266 AST_OPTIONAL_API_ATTR_USER(result, attr, name, proto, stub)
267
268#endif /* defined(AST_API_MODULE) */
269
270#endif /* defined(OPTIONAL_API) */
271
272#undef AST_API_MODULE
#define attribute_may_alias
Definition: compiler.h:77