Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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  */
122 typedef 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  */
133 void 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  */
144 void 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  */
158 void 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  */
172 void 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
void ast_optional_api_provide(const char *symname, ast_optional_fn impl)
Definition: optional_api.c:212
ast_optional_fn impl
Definition: optional_api.c:59
void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl)
Definition: optional_api.c:222
void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref, ast_optional_fn stub, const char *module)
Definition: optional_api.c:232
void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref, const char *module)
Definition: optional_api.c:257
#define attribute_may_alias
Definition: compiler.h:77