rpc.hh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /* RPC call and callback templates
  2. Copyright (C) 2014 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free
  6. Software Foundation; either version 3, or (at your option) any later
  7. version.
  8. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GCC; see the file COPYING3. If not see
  14. <http://www.gnu.org/licenses/>. */
  15. #ifndef CC1_PLUGIN_RPC_HH
  16. #define CC1_PLUGIN_RPC_HH
  17. #include "status.hh"
  18. #include "marshall.hh"
  19. #include "connection.hh"
  20. namespace cc1_plugin
  21. {
  22. // The plugin API may contain some "const" method parameters.
  23. // However, when unmarshalling we cannot unmarshall into a const
  24. // object; and furthermore we want to be able to deallocate pointers
  25. // when finished with them. This wrapper class lets us properly
  26. // remove the "const" and handle deallocation from pointer types.
  27. template<typename T>
  28. class argument_wrapper
  29. {
  30. public:
  31. argument_wrapper () { }
  32. ~argument_wrapper () { }
  33. operator T () const { return m_object; }
  34. status unmarshall (connection *conn)
  35. {
  36. return ::cc1_plugin::unmarshall (conn, &m_object);
  37. }
  38. private:
  39. T m_object;
  40. // No copying or assignment allowed.
  41. argument_wrapper (const argument_wrapper &);
  42. argument_wrapper &operator= (const argument_wrapper &);
  43. };
  44. // Specialization for any kind of pointer. This is declared but not
  45. // defined to avoid bugs if a new pointer type is introduced into
  46. // the API. Instead you will just get a compilation error.
  47. template<typename T>
  48. class argument_wrapper<const T *>;
  49. // Specialization for string types.
  50. template<>
  51. class argument_wrapper<const char *>
  52. {
  53. public:
  54. argument_wrapper () : m_object (NULL) { }
  55. ~argument_wrapper ()
  56. {
  57. delete[] m_object;
  58. }
  59. operator const char * () const
  60. {
  61. return m_object;
  62. }
  63. status unmarshall (connection *conn)
  64. {
  65. return ::cc1_plugin::unmarshall (conn, &m_object);
  66. }
  67. private:
  68. char *m_object;
  69. // No copying or assignment allowed.
  70. argument_wrapper (const argument_wrapper &);
  71. argument_wrapper &operator= (const argument_wrapper &);
  72. };
  73. // Specialization for gcc_type_array.
  74. template<>
  75. class argument_wrapper<const gcc_type_array *>
  76. {
  77. public:
  78. argument_wrapper () : m_object (NULL) { }
  79. ~argument_wrapper ()
  80. {
  81. // It would be nicer if gcc_type_array could have a destructor.
  82. // But, it is in code shared with gdb and cannot.
  83. if (m_object != NULL)
  84. delete[] m_object->elements;
  85. delete m_object;
  86. }
  87. operator const gcc_type_array * () const
  88. {
  89. return m_object;
  90. }
  91. status unmarshall (connection *conn)
  92. {
  93. return ::cc1_plugin::unmarshall (conn, &m_object);
  94. }
  95. private:
  96. gcc_type_array *m_object;
  97. // No copying or assignment allowed.
  98. argument_wrapper (const argument_wrapper &);
  99. argument_wrapper &operator= (const argument_wrapper &);
  100. };
  101. // There are two kinds of template functions here: "call" and
  102. // "callback". They are each repeated multiple times to handle
  103. // different numbers of arguments. (This would be improved with
  104. // C++11, though applying a call is still tricky until C++14 can be
  105. // used.)
  106. // The "call" template is used for making a remote procedure call.
  107. // It starts a query ('Q') packet, marshalls its arguments, waits
  108. // for a result, and finally reads and returns the result via an
  109. // "out" parameter.
  110. // The "callback" template is used when receiving a remote procedure
  111. // call. This template function is suitable for use with the
  112. // "callbacks" and "connection" classes. It decodes incoming
  113. // arguments, passes them to the wrapped function, and finally
  114. // marshalls a reply packet.
  115. template<typename R>
  116. status
  117. call (connection *conn, const char *method, R *result)
  118. {
  119. if (!conn->send ('Q'))
  120. return FAIL;
  121. if (!marshall (conn, method))
  122. return FAIL;
  123. if (!marshall (conn, 0))
  124. return FAIL;
  125. if (!conn->wait_for_result ())
  126. return FAIL;
  127. if (!unmarshall (conn, result))
  128. return FAIL;
  129. return OK;
  130. }
  131. template<typename R, R (*func) (connection *)>
  132. status
  133. callback (connection *conn)
  134. {
  135. R result;
  136. if (!unmarshall_check (conn, 0))
  137. return FAIL;
  138. result = func (conn);
  139. if (!conn->send ('R'))
  140. return FAIL;
  141. return marshall (conn, result);
  142. }
  143. template<typename R, typename A>
  144. status
  145. call (connection *conn, const char *method, R *result, A arg)
  146. {
  147. if (!conn->send ('Q'))
  148. return FAIL;
  149. if (!marshall (conn, method))
  150. return FAIL;
  151. if (!marshall (conn, 1))
  152. return FAIL;
  153. if (!marshall (conn, arg))
  154. return FAIL;
  155. if (!conn->wait_for_result ())
  156. return FAIL;
  157. if (!unmarshall (conn, result))
  158. return FAIL;
  159. return OK;
  160. }
  161. template<typename R, typename A, R (*func) (connection *, A)>
  162. status
  163. callback (connection *conn)
  164. {
  165. argument_wrapper<A> arg;
  166. R result;
  167. if (!unmarshall_check (conn, 1))
  168. return FAIL;
  169. if (!arg.unmarshall (conn))
  170. return FAIL;
  171. result = func (conn, arg);
  172. if (!conn->send ('R'))
  173. return FAIL;
  174. return marshall (conn, result);
  175. }
  176. template<typename R, typename A1, typename A2>
  177. status
  178. call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
  179. {
  180. if (!conn->send ('Q'))
  181. return FAIL;
  182. if (!marshall (conn, method))
  183. return FAIL;
  184. if (!marshall (conn, 2))
  185. return FAIL;
  186. if (!marshall (conn, arg1))
  187. return FAIL;
  188. if (!marshall (conn, arg2))
  189. return FAIL;
  190. if (!conn->wait_for_result ())
  191. return FAIL;
  192. if (!unmarshall (conn, result))
  193. return FAIL;
  194. return OK;
  195. }
  196. template<typename R, typename A1, typename A2, R (*func) (connection *,
  197. A1, A2)>
  198. status
  199. callback (connection *conn)
  200. {
  201. argument_wrapper<A1> arg1;
  202. argument_wrapper<A2> arg2;
  203. R result;
  204. if (!unmarshall_check (conn, 2))
  205. return FAIL;
  206. if (!arg1.unmarshall (conn))
  207. return FAIL;
  208. if (!arg2.unmarshall (conn))
  209. return FAIL;
  210. result = func (conn, arg1, arg2);
  211. if (!conn->send ('R'))
  212. return FAIL;
  213. return marshall (conn, result);
  214. }
  215. template<typename R, typename A1, typename A2, typename A3>
  216. status
  217. call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
  218. A3 arg3)
  219. {
  220. if (!conn->send ('Q'))
  221. return FAIL;
  222. if (!marshall (conn, method))
  223. return FAIL;
  224. if (!marshall (conn, 3))
  225. return FAIL;
  226. if (!marshall (conn, arg1))
  227. return FAIL;
  228. if (!marshall (conn, arg2))
  229. return FAIL;
  230. if (!marshall (conn, arg3))
  231. return FAIL;
  232. if (!conn->wait_for_result ())
  233. return FAIL;
  234. if (!unmarshall (conn, result))
  235. return FAIL;
  236. return OK;
  237. }
  238. template<typename R, typename A1, typename A2, typename A3,
  239. R (*func) (connection *, A1, A2, A3)>
  240. status
  241. callback (connection *conn)
  242. {
  243. argument_wrapper<A1> arg1;
  244. argument_wrapper<A2> arg2;
  245. argument_wrapper<A3> arg3;
  246. R result;
  247. if (!unmarshall_check (conn, 3))
  248. return FAIL;
  249. if (!arg1.unmarshall (conn))
  250. return FAIL;
  251. if (!arg2.unmarshall (conn))
  252. return FAIL;
  253. if (!arg3.unmarshall (conn))
  254. return FAIL;
  255. result = func (conn, arg1, arg2, arg3);
  256. if (!conn->send ('R'))
  257. return FAIL;
  258. return marshall (conn, result);
  259. }
  260. template<typename R, typename A1, typename A2, typename A3, typename A4>
  261. status
  262. call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
  263. A3 arg3, A4 arg4)
  264. {
  265. if (!conn->send ('Q'))
  266. return FAIL;
  267. if (!marshall (conn, method))
  268. return FAIL;
  269. if (!marshall (conn, 4))
  270. return FAIL;
  271. if (!marshall (conn, arg1))
  272. return FAIL;
  273. if (!marshall (conn, arg2))
  274. return FAIL;
  275. if (!marshall (conn, arg3))
  276. return FAIL;
  277. if (!marshall (conn, arg4))
  278. return FAIL;
  279. if (!conn->wait_for_result ())
  280. return FAIL;
  281. if (!unmarshall (conn, result))
  282. return FAIL;
  283. return OK;
  284. }
  285. template<typename R, typename A1, typename A2, typename A3, typename A4,
  286. R (*func) (connection *, A1, A2, A3, A4)>
  287. status
  288. callback (connection *conn)
  289. {
  290. argument_wrapper<A1> arg1;
  291. argument_wrapper<A2> arg2;
  292. argument_wrapper<A3> arg3;
  293. argument_wrapper<A4> arg4;
  294. R result;
  295. if (!unmarshall_check (conn, 4))
  296. return FAIL;
  297. if (!arg1.unmarshall (conn))
  298. return FAIL;
  299. if (!arg2.unmarshall (conn))
  300. return FAIL;
  301. if (!arg3.unmarshall (conn))
  302. return FAIL;
  303. if (!arg4.unmarshall (conn))
  304. return FAIL;
  305. result = func (conn, arg1, arg2, arg3, arg4);
  306. if (!conn->send ('R'))
  307. return FAIL;
  308. return marshall (conn, result);
  309. }
  310. template<typename R, typename A1, typename A2, typename A3, typename A4,
  311. typename A5>
  312. status
  313. call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
  314. A3 arg3, A4 arg4, A5 arg5)
  315. {
  316. if (!conn->send ('Q'))
  317. return FAIL;
  318. if (!marshall (conn, method))
  319. return FAIL;
  320. if (!marshall (conn, 5))
  321. return FAIL;
  322. if (!marshall (conn, arg1))
  323. return FAIL;
  324. if (!marshall (conn, arg2))
  325. return FAIL;
  326. if (!marshall (conn, arg3))
  327. return FAIL;
  328. if (!marshall (conn, arg4))
  329. return FAIL;
  330. if (!marshall (conn, arg5))
  331. return FAIL;
  332. if (!conn->wait_for_result ())
  333. return FAIL;
  334. if (!unmarshall (conn, result))
  335. return FAIL;
  336. return OK;
  337. }
  338. template<typename R, typename A1, typename A2, typename A3, typename A4,
  339. typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
  340. status
  341. callback (connection *conn)
  342. {
  343. argument_wrapper<A1> arg1;
  344. argument_wrapper<A2> arg2;
  345. argument_wrapper<A3> arg3;
  346. argument_wrapper<A4> arg4;
  347. argument_wrapper<A5> arg5;
  348. R result;
  349. if (!unmarshall_check (conn, 5))
  350. return FAIL;
  351. if (!arg1.unmarshall (conn))
  352. return FAIL;
  353. if (!arg2.unmarshall (conn))
  354. return FAIL;
  355. if (!arg3.unmarshall (conn))
  356. return FAIL;
  357. if (!arg4.unmarshall (conn))
  358. return FAIL;
  359. if (!arg5.unmarshall (conn))
  360. return FAIL;
  361. result = func (conn, arg1, arg2, arg3, arg4, arg5);
  362. if (!conn->send ('R'))
  363. return FAIL;
  364. return marshall (conn, result);
  365. }
  366. template<typename R, typename A1, typename A2, typename A3, typename A4,
  367. typename A5, typename A6, typename A7>
  368. status
  369. call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
  370. A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
  371. {
  372. if (!conn->send ('Q'))
  373. return FAIL;
  374. if (!marshall (conn, method))
  375. return FAIL;
  376. if (!marshall (conn, 7))
  377. return FAIL;
  378. if (!marshall (conn, arg1))
  379. return FAIL;
  380. if (!marshall (conn, arg2))
  381. return FAIL;
  382. if (!marshall (conn, arg3))
  383. return FAIL;
  384. if (!marshall (conn, arg4))
  385. return FAIL;
  386. if (!marshall (conn, arg5))
  387. return FAIL;
  388. if (!marshall (conn, arg6))
  389. return FAIL;
  390. if (!marshall (conn, arg7))
  391. return FAIL;
  392. if (!conn->wait_for_result ())
  393. return FAIL;
  394. if (!unmarshall (conn, result))
  395. return FAIL;
  396. return OK;
  397. }
  398. template<typename R, typename A1, typename A2, typename A3, typename A4,
  399. typename A5, typename A6, typename A7,
  400. R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>
  401. status
  402. callback (connection *conn)
  403. {
  404. argument_wrapper<A1> arg1;
  405. argument_wrapper<A2> arg2;
  406. argument_wrapper<A3> arg3;
  407. argument_wrapper<A4> arg4;
  408. argument_wrapper<A5> arg5;
  409. argument_wrapper<A6> arg6;
  410. argument_wrapper<A7> arg7;
  411. R result;
  412. if (!unmarshall_check (conn, 7))
  413. return FAIL;
  414. if (!arg1.unmarshall (conn))
  415. return FAIL;
  416. if (!arg2.unmarshall (conn))
  417. return FAIL;
  418. if (!arg3.unmarshall (conn))
  419. return FAIL;
  420. if (!arg4.unmarshall (conn))
  421. return FAIL;
  422. if (!arg5.unmarshall (conn))
  423. return FAIL;
  424. if (!arg6.unmarshall (conn))
  425. return FAIL;
  426. if (!arg7.unmarshall (conn))
  427. return FAIL;
  428. result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  429. if (!conn->send ('R'))
  430. return FAIL;
  431. return marshall (conn, result);
  432. }
  433. };
  434. #endif // CC1_PLUGIN_RPC_HH