Callback_06.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /**
  2. * Example code for:
  3. * - callback storage with std::vector
  4. * - use of std::function
  5. * - use of std::bind
  6. * - use of lambda function as callback
  7. */
  8. #include <cstdint>
  9. #include <cstdio>
  10. #include <functional>
  11. #include <vector>
  12. /**
  13. * Basic std::function callback example. Templated on a function signature
  14. * that takes in a uint32_t and returns void.
  15. */
  16. typedef std::function<void(uint32_t)> cb_t;
  17. /**
  18. * Here's an example type that stores a std::function and an argument
  19. * to pass with that callback. Passing a uint32_t input to your callback
  20. * is a pretty common implementation. Also useful if you need to store a
  21. * pointer for use with a BOUNCE function.
  22. */
  23. struct cb_arg_t
  24. {
  25. // the callback - takes a uint32_t input.
  26. std::function<void(uint32_t)> cb;
  27. // value to return with the callback.
  28. uint32_t arg;
  29. };
  30. /**
  31. * Alternative storage implementation. Perhaps you want to store
  32. * callbacks for different event types?
  33. */
  34. enum my_events_t
  35. {
  36. VIDEO_STOP = 0,
  37. VIDEO_START,
  38. EVENT_MAX
  39. };
  40. struct cb_event_t
  41. {
  42. std::function<void(uint32_t)> cb;
  43. my_events_t event;
  44. };
  45. /**
  46. * Basic example. Constructed with a uint32_t.
  47. * Callbacks are passed this uint32_t.
  48. */
  49. class BasicDriver
  50. {
  51. public:
  52. BasicDriver(uint32_t val) : val_(val), callbacks_()
  53. {
  54. }
  55. // Register a callback.
  56. void register_callback(const cb_t& cb)
  57. {
  58. // add callback to end of callback list
  59. callbacks_.push_back(cb);
  60. }
  61. /// Call all the registered callbacks.
  62. void callback() const
  63. {
  64. // iterate through callback list and call each one
  65. for (const auto& cb : callbacks_)
  66. {
  67. cb(val_);
  68. }
  69. }
  70. private:
  71. /// Integer to pass to callbacks.
  72. uint32_t val_;
  73. /// List of callback functions.
  74. std::vector<cb_t> callbacks_;
  75. };
  76. /**
  77. * Event based example. Constructed with a uint32_t.
  78. * Callbacks are passed this uint32_t.
  79. * Callbacks are only invoked when their event type matches the
  80. * occuring event.
  81. */
  82. class EventDriver
  83. {
  84. public:
  85. EventDriver(uint32_t val) : val_(val), callbacks_()
  86. {
  87. }
  88. // Register a callback.
  89. void register_callback(const cb_t& cb, const my_events_t event)
  90. {
  91. // add callback to end of callback list
  92. callbacks_.push_back({ cb, event });
  93. }
  94. /// Call all the registered callbacks.
  95. void callback() const
  96. {
  97. my_events_t event = VIDEO_START;
  98. // iterate through callback list and call each one
  99. for (const auto& cb : callbacks_)
  100. {
  101. if (cb.event == event)
  102. {
  103. cb.cb(val_);
  104. }
  105. }
  106. }
  107. private:
  108. /// Integer to pass to callbacks.
  109. uint32_t val_;
  110. /// List of callback functions.
  111. std::vector<cb_event_t> callbacks_;
  112. };
  113. /**
  114. * Arg based example.
  115. * Callbacks register with a uint32_t that they want returned
  116. * Callbacks always passed their specific uint32_t value
  117. */
  118. class ArgDriver
  119. {
  120. public:
  121. ArgDriver() : callbacks_()
  122. {
  123. }
  124. // Register a callback.
  125. void register_callback(const cb_t& cb, const uint32_t val)
  126. {
  127. // add callback to end of callback list
  128. callbacks_.push_back({ cb, val });
  129. }
  130. /// Call all the registered callbacks.
  131. void callback() const
  132. {
  133. // iterate through callback list and call each one
  134. for (const auto& cb : callbacks_)
  135. {
  136. cb.cb(cb.arg);
  137. }
  138. }
  139. private:
  140. /// List of callback functions.
  141. std::vector<cb_arg_t> callbacks_;
  142. };
  143. /**
  144. * Dummy Client #1
  145. * Uses a static method for a callback.
  146. */
  147. class Client1
  148. {
  149. public:
  150. static void func(uint32_t v)
  151. {
  152. printf("static member callback: 0x%x\n", v);
  153. }
  154. };
  155. /**
  156. * Dummy Client #2
  157. * Uses an instance method as a callback
  158. */
  159. class Client2
  160. {
  161. public:
  162. void func(uint32_t v) const
  163. {
  164. printf("instance member callback: 0x%x\n", v);
  165. }
  166. };
  167. /**
  168. * Callback on a c function
  169. */
  170. extern "C"
  171. {
  172. static void c_client_callback(uint32_t v)
  173. {
  174. printf("C function callback: 0x%x\n", v);
  175. }
  176. }
  177. int main()
  178. {
  179. /**
  180. * Examples using the basic driver
  181. * This is constructed with a specific value
  182. * Each callback receives this value
  183. */
  184. BasicDriver bd(0xDEADBEEF); // create basic driver instance
  185. Client2 c2;
  186. printf("Starting examples using the BasicDriver\n");
  187. // register a lambda function as a callback
  188. bd.register_callback([](uint32_t v) {
  189. printf("lambda callback: 0x%x\n", v);
  190. });
  191. /**
  192. * std::bind is used to create a function object using
  193. * both the instance and method pointers. This gives you the
  194. * callback into the specific object - very useful!
  195. *
  196. * std::bind keeps specific arguments at a fixed value (or a placeholder)
  197. * For our argument here, we keep as a placeholder.
  198. */
  199. bd.register_callback(std::bind(&Client2::func, &c2, std::placeholders::_1));
  200. // register a static class method as a callback
  201. bd.register_callback(&Client1::func);
  202. // register a C function pointer as a callback
  203. bd.register_callback(&c_client_callback);
  204. // call all the registered callbacks
  205. bd.callback();
  206. printf("End of examples using the BasicDriver\n");
  207. /**
  208. * Examples using the Event Driver.
  209. * Note that some callbacks will not be called -
  210. * their event type is different!
  211. */
  212. EventDriver ed(0xFEEDBEEF);
  213. printf("Beginning of examples using the EventDriver\n");
  214. // register a lambda function as a callback
  215. ed.register_callback(
  216. [](uint32_t v) {
  217. printf("lambda callback: 0x%x\n", v);
  218. },
  219. VIDEO_START);
  220. // register client2 cb using std::bind
  221. ed.register_callback(std::bind(&Client2::func, &c2, std::placeholders::_1), VIDEO_STOP);
  222. // register a static class method as a callback
  223. ed.register_callback(&Client1::func, VIDEO_STOP);
  224. // register a C function pointer as a callback
  225. ed.register_callback(&c_client_callback, VIDEO_START);
  226. // call all the registered callbacks
  227. ed.callback();
  228. printf("End of examples using the EventDriver\n");
  229. /**
  230. * Examples using the Arg Driver.
  231. * Note that each callback registers for its own value
  232. */
  233. ArgDriver ad;
  234. printf("Beginning of examples using the ArgDriver\n");
  235. // register a lambda function as a callback
  236. ad.register_callback(
  237. [](uint32_t v) {
  238. printf("lambda callback: 0x%x\n", v);
  239. },
  240. 0x0);
  241. // register client2 cb using std::bind
  242. ad.register_callback(std::bind(&Client2::func, &c2, std::placeholders::_1), 0x1);
  243. // register a static class method as a callback
  244. ad.register_callback(&Client1::func, 0x2);
  245. // register a C function pointer as a callback
  246. ad.register_callback(&c_client_callback, 0x3);
  247. // call all the registered callbacks
  248. ad.callback();
  249. printf("End of examples using the ArgDriver\n");
  250. return 0;
  251. }