optional_api.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. #ifndef __ASTERISK_OPTIONAL_API_H
  19. #define __ASTERISK_OPTIONAL_API_H
  20. /*!
  21. * \file
  22. * \brief Optional API function macros
  23. *
  24. * Some Asterisk API functions are provided by loadable modules, thus,
  25. * they may or may not be available at run time depending on whether the
  26. * providing module has been loaded or not. In addition, there are some
  27. * modules that are consumers of these APIs that *optionally* use them; they
  28. * have only a part of their functionality dependent on the APIs, and can
  29. * provide the remainder even if the APIs are not available.
  30. *
  31. * An example can be found in agi.h:
  32. *
  33. * \code
  34. * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
  35. * { return AST_OPTIONAL_API_UNAVAILABLE; });
  36. * \endcode
  37. *
  38. * This defines the 'ast_agi_register' function as an optional API; if a
  39. * consumer of this API is loaded when there is no provider of it, then
  40. * calling this function will actually call the hidden stub, and return
  41. * the value AST_OPTIONAL_API_UNAVAILABLE. This allows the consumer to
  42. * safely know that the API is not available, and to avoid using any
  43. * other APIs from the not-present provider.
  44. *
  45. * In addition to this declaration in the header file, the actual definition of
  46. * the API function must use the AST_OPTIONAL_API_NAME macro to (possibly)
  47. * modify the real name of the API function, depending on the specific
  48. * implementation requirements. The corresponding example from res_agi.c:
  49. *
  50. * \code
  51. * int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
  52. * {
  53. * ...
  54. * }
  55. * \endcode
  56. *
  57. * In the module providing the API, the AST_OPTIONAL_API macro must
  58. * be informed that it should not build the hidden stub function or
  59. * apply special aliases to the function prototype; this can be done
  60. * by defining AST_API_MODULE just before including the header file
  61. * containing the AST_OPTIONAL_API macro calls.
  62. */
  63. /*!
  64. * \brief A common value for optional API stub functions to return
  65. *
  66. * This value is defined as INT_MIN, the minimum value for an integer
  67. * (maximum negative value), which can be used by any optional API
  68. * functions that return a signed integer value and would not be
  69. * able to return such a value under normal circumstances.
  70. */
  71. #define AST_OPTIONAL_API_UNAVAILABLE INT_MIN
  72. /*!
  73. * \def AST_OPTIONAL_API_NAME(name)
  74. * \brief Expands to the name of the implementation function.
  75. */
  76. /*!
  77. * \def AST_OPTIONAL_API(result, name, proto, stub)
  78. * \brief Declare an optional API function
  79. *
  80. * \param result The type of result the function returns
  81. * \param name The name of the function
  82. * \param proto The prototype (arguments) of the function
  83. * \param stub The code block that will be used by the hidden stub when needed
  84. *
  85. * Example usage:
  86. * \code
  87. * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
  88. * { return AST_OPTIONAL_API_UNAVAILABLE; });
  89. * \endcode
  90. */
  91. /*!
  92. * \def AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)
  93. * \brief Declare an optional API function with compiler attributes
  94. *
  95. * \param result The type of result the function returns
  96. * \param attr Any compiler attributes to be applied to the function (without the __attribute__ wrapper)
  97. * \param name The name of the function
  98. * \param proto The prototype (arguments) of the function
  99. * \param stub The code block that will be used by the hidden stub when needed
  100. */
  101. #if defined(OPTIONAL_API)
  102. /*!
  103. * \internal
  104. * \brief Function pointer to an optional API function.
  105. *
  106. * Functions that are declared as optional may have any signature they want;
  107. * they are cast to this type as needed. We don't use a \c void pointer, because
  108. * technically data and function pointers are incompatible.
  109. *
  110. * \note
  111. * The may_alias attribute is to avoid type punning/strict aliasing warnings
  112. * with older GCC's.
  113. */
  114. typedef void (*ast_optional_fn)(void) attribute_may_alias;
  115. /*!
  116. * \internal
  117. * \brief Provide an implementation of an optional API.
  118. *
  119. * Any declared usages of this function are linked.
  120. *
  121. * \param symname Name of the provided function.
  122. * \param impl Function pointer to the implementation function.
  123. */
  124. void ast_optional_api_provide(const char *symname, ast_optional_fn impl);
  125. /*!
  126. * \internal
  127. * \brief Remove an implementation of an optional API.
  128. *
  129. * Any declared usages of this function are unlinked.
  130. *
  131. * \param symname Name of the provided function.
  132. * \param impl Function pointer to the implementation function.
  133. */
  134. void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl);
  135. /*!
  136. * \internal
  137. * \brief Define a usage of an optional API.
  138. *
  139. * If the API has been provided, it will be linked into \a optional_ref.
  140. * Otherwise, it will be linked to \a stub until an implementation is provided.
  141. *
  142. * \param symname Name of the function to use.
  143. * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
  144. * \param stub Stub function to link to when impl is not available.
  145. * \param module Name of the module requesting the API.
  146. */
  147. void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
  148. ast_optional_fn stub, const char *module);
  149. /*!
  150. * \internal
  151. * \brief Remove a usage of an optional API.
  152. *
  153. * The \a optional_ref will be linked to the \a stub provided at use time,
  154. * will no longer be updated if the API is provided/removed.
  155. *
  156. * \param symname Name of the function to use.
  157. * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
  158. * \param module Name of the module requesting the API.
  159. */
  160. void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,
  161. const char *module);
  162. #define AST_OPTIONAL_API_NAME(name) __##name
  163. #if defined(AST_API_MODULE)
  164. /* Module defining the API */
  165. #define AST_OPTIONAL_API_IMPL_INIT(name) \
  166. static void __attribute__((constructor)) __init__##name##_impl(void) { \
  167. ast_optional_api_provide(#name, \
  168. (ast_optional_fn)AST_OPTIONAL_API_NAME(name)); \
  169. } \
  170. static void __attribute__((destructor)) __dtor__##name##_impl(void) { \
  171. ast_optional_api_unprovide(#name, \
  172. (ast_optional_fn)AST_OPTIONAL_API_NAME(name)); \
  173. }
  174. #define AST_OPTIONAL_API(result, name, proto, stub) \
  175. result AST_OPTIONAL_API_NAME(name) proto; \
  176. static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
  177. name = AST_OPTIONAL_API_NAME(name); \
  178. AST_OPTIONAL_API_IMPL_INIT(name)
  179. #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
  180. result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
  181. static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
  182. name = AST_OPTIONAL_API_NAME(name); \
  183. AST_OPTIONAL_API_IMPL_INIT(name)
  184. #else
  185. /* Module using the API */
  186. #define AST_OPTIONAL_API_INIT(name) \
  187. static void __attribute__((constructor)) __init__##name(void) { \
  188. ast_optional_api_use(#name, (ast_optional_fn *)&name, \
  189. (ast_optional_fn)__stub__##name, \
  190. AST_MODULE); \
  191. } \
  192. static void __attribute__((destructor)) __dtor__##name(void) { \
  193. ast_optional_api_unuse(#name, (ast_optional_fn *)&name, \
  194. AST_MODULE); \
  195. }
  196. #define AST_OPTIONAL_API(result, name, proto, stub) \
  197. static result __stub__##name proto stub; \
  198. static attribute_unused \
  199. typeof(__stub__##name) * name; \
  200. AST_OPTIONAL_API_INIT(name)
  201. #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
  202. static __attribute__((attr)) result __stub__##name proto stub; \
  203. static attribute_unused __attribute__((attr)) \
  204. typeof(__stub__##name) * name; \
  205. AST_OPTIONAL_API_INIT(name)
  206. #endif /* defined(AST_API_MODULE) */
  207. #else /* defined(OPTIONAL_API) */
  208. /* Non-optional API */
  209. #define AST_OPTIONAL_API_NAME(name) name
  210. #define AST_OPTIONAL_API(result, name, proto, stub) \
  211. result AST_OPTIONAL_API_NAME(name) proto
  212. #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
  213. result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto
  214. #endif /* defined(OPTIONAL_API) */
  215. #undef AST_API_MODULE
  216. #endif /* __ASTERISK_OPTIONAL_API_H */