1 /* RPC call and callback templates
2 Copyright (C) 2014-2017 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #ifndef CC1_PLUGIN_RPC_HH
21 #define CC1_PLUGIN_RPC_HH
24 #include "connection.hh"
28 // The plugin API may contain some "const" method parameters.
29 // However, when unmarshalling we cannot unmarshall into a const
30 // object; and furthermore we want to be able to deallocate pointers
31 // when finished with them. This wrapper class lets us properly
32 // remove the "const" and handle deallocation from pointer types.
35 class argument_wrapper
39 argument_wrapper () { }
40 ~argument_wrapper () { }
42 operator T () const { return m_object; }
44 status unmarshall (connection *conn)
46 return ::cc1_plugin::unmarshall (conn, &m_object);
53 // No copying or assignment allowed.
54 argument_wrapper (const argument_wrapper &);
55 argument_wrapper &operator= (const argument_wrapper &);
58 // Specialization for any kind of pointer. This is declared but not
59 // defined to avoid bugs if a new pointer type is introduced into
60 // the API. Instead you will just get a compilation error.
62 class argument_wrapper<const T *>;
64 // Specialization for string types.
66 class argument_wrapper<const char *>
69 argument_wrapper () : m_object (NULL) { }
75 operator const char * () const
80 status unmarshall (connection *conn)
82 return ::cc1_plugin::unmarshall (conn, &m_object);
89 // No copying or assignment allowed.
90 argument_wrapper (const argument_wrapper &);
91 argument_wrapper &operator= (const argument_wrapper &);
94 // Specialization for gcc_type_array.
96 class argument_wrapper<const gcc_type_array *>
99 argument_wrapper () : m_object (NULL) { }
102 // It would be nicer if gcc_type_array could have a destructor.
103 // But, it is in code shared with gdb and cannot.
104 if (m_object != NULL)
105 delete[] m_object->elements;
109 operator const gcc_type_array * () const
114 status unmarshall (connection *conn)
116 return ::cc1_plugin::unmarshall (conn, &m_object);
121 gcc_type_array *m_object;
123 // No copying or assignment allowed.
124 argument_wrapper (const argument_wrapper &);
125 argument_wrapper &operator= (const argument_wrapper &);
128 #ifdef GCC_CP_INTERFACE_H
129 // Specialization for gcc_vbase_array.
131 class argument_wrapper<const gcc_vbase_array *>
134 argument_wrapper () : m_object (NULL) { }
137 // It would be nicer if gcc_type_array could have a destructor.
138 // But, it is in code shared with gdb and cannot.
139 if (m_object != NULL)
141 delete[] m_object->flags;
142 delete[] m_object->elements;
147 operator const gcc_vbase_array * () const
152 status unmarshall (connection *conn)
154 return ::cc1_plugin::unmarshall (conn, &m_object);
159 gcc_vbase_array *m_object;
161 // No copying or assignment allowed.
162 argument_wrapper (const argument_wrapper &);
163 argument_wrapper &operator= (const argument_wrapper &);
166 // Specialization for gcc_cp_template_args.
168 class argument_wrapper<const gcc_cp_template_args *>
171 argument_wrapper () : m_object (NULL) { }
174 // It would be nicer if gcc_type_array could have a destructor.
175 // But, it is in code shared with gdb and cannot.
176 if (m_object != NULL)
178 delete[] m_object->elements;
179 delete[] m_object->kinds;
184 operator const gcc_cp_template_args * () const
189 status unmarshall (connection *conn)
191 return ::cc1_plugin::unmarshall (conn, &m_object);
196 gcc_cp_template_args *m_object;
198 // No copying or assignment allowed.
199 argument_wrapper (const argument_wrapper &);
200 argument_wrapper &operator= (const argument_wrapper &);
203 // Specialization for gcc_cp_function_args.
205 class argument_wrapper<const gcc_cp_function_args *>
208 argument_wrapper () : m_object (NULL) { }
211 // It would be nicer if gcc_type_array could have a destructor.
212 // But, it is in code shared with gdb and cannot.
213 if (m_object != NULL)
215 delete[] m_object->elements;
220 operator const gcc_cp_function_args * () const
225 status unmarshall (connection *conn)
227 return ::cc1_plugin::unmarshall (conn, &m_object);
232 gcc_cp_function_args *m_object;
234 // No copying or assignment allowed.
235 argument_wrapper (const argument_wrapper &);
236 argument_wrapper &operator= (const argument_wrapper &);
238 #endif /* GCC_CP_INTERFACE_H */
240 // There are two kinds of template functions here: "call" and
241 // "callback". They are each repeated multiple times to handle
242 // different numbers of arguments. (This would be improved with
243 // C++11, though applying a call is still tricky until C++14 can be
246 // The "call" template is used for making a remote procedure call.
247 // It starts a query ('Q') packet, marshalls its arguments, waits
248 // for a result, and finally reads and returns the result via an
251 // The "callback" template is used when receiving a remote procedure
252 // call. This template function is suitable for use with the
253 // "callbacks" and "connection" classes. It decodes incoming
254 // arguments, passes them to the wrapped function, and finally
255 // marshalls a reply packet.
259 call (connection *conn, const char *method, R *result)
261 if (!conn->send ('Q'))
263 if (!marshall (conn, method))
265 if (!marshall (conn, 0))
267 if (!conn->wait_for_result ())
269 if (!unmarshall (conn, result))
274 template<typename R, R (*func) (connection *)>
276 callback (connection *conn)
280 if (!unmarshall_check (conn, 0))
282 result = func (conn);
283 if (!conn->send ('R'))
285 return marshall (conn, result);
288 template<typename R, typename A>
290 call (connection *conn, const char *method, R *result, A arg)
292 if (!conn->send ('Q'))
294 if (!marshall (conn, method))
296 if (!marshall (conn, 1))
298 if (!marshall (conn, arg))
300 if (!conn->wait_for_result ())
302 if (!unmarshall (conn, result))
307 template<typename R, typename A, R (*func) (connection *, A)>
309 callback (connection *conn)
311 argument_wrapper<A> arg;
314 if (!unmarshall_check (conn, 1))
316 if (!arg.unmarshall (conn))
318 result = func (conn, arg);
319 if (!conn->send ('R'))
321 return marshall (conn, result);
324 template<typename R, typename A1, typename A2>
326 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
328 if (!conn->send ('Q'))
330 if (!marshall (conn, method))
332 if (!marshall (conn, 2))
334 if (!marshall (conn, arg1))
336 if (!marshall (conn, arg2))
338 if (!conn->wait_for_result ())
340 if (!unmarshall (conn, result))
345 template<typename R, typename A1, typename A2, R (*func) (connection *,
348 callback (connection *conn)
350 argument_wrapper<A1> arg1;
351 argument_wrapper<A2> arg2;
354 if (!unmarshall_check (conn, 2))
356 if (!arg1.unmarshall (conn))
358 if (!arg2.unmarshall (conn))
360 result = func (conn, arg1, arg2);
361 if (!conn->send ('R'))
363 return marshall (conn, result);
366 template<typename R, typename A1, typename A2, typename A3>
368 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
371 if (!conn->send ('Q'))
373 if (!marshall (conn, method))
375 if (!marshall (conn, 3))
377 if (!marshall (conn, arg1))
379 if (!marshall (conn, arg2))
381 if (!marshall (conn, arg3))
383 if (!conn->wait_for_result ())
385 if (!unmarshall (conn, result))
390 template<typename R, typename A1, typename A2, typename A3,
391 R (*func) (connection *, A1, A2, A3)>
393 callback (connection *conn)
395 argument_wrapper<A1> arg1;
396 argument_wrapper<A2> arg2;
397 argument_wrapper<A3> arg3;
400 if (!unmarshall_check (conn, 3))
402 if (!arg1.unmarshall (conn))
404 if (!arg2.unmarshall (conn))
406 if (!arg3.unmarshall (conn))
408 result = func (conn, arg1, arg2, arg3);
409 if (!conn->send ('R'))
411 return marshall (conn, result);
414 template<typename R, typename A1, typename A2, typename A3, typename A4>
416 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
419 if (!conn->send ('Q'))
421 if (!marshall (conn, method))
423 if (!marshall (conn, 4))
425 if (!marshall (conn, arg1))
427 if (!marshall (conn, arg2))
429 if (!marshall (conn, arg3))
431 if (!marshall (conn, arg4))
433 if (!conn->wait_for_result ())
435 if (!unmarshall (conn, result))
440 template<typename R, typename A1, typename A2, typename A3, typename A4,
441 R (*func) (connection *, A1, A2, A3, A4)>
443 callback (connection *conn)
445 argument_wrapper<A1> arg1;
446 argument_wrapper<A2> arg2;
447 argument_wrapper<A3> arg3;
448 argument_wrapper<A4> arg4;
451 if (!unmarshall_check (conn, 4))
453 if (!arg1.unmarshall (conn))
455 if (!arg2.unmarshall (conn))
457 if (!arg3.unmarshall (conn))
459 if (!arg4.unmarshall (conn))
461 result = func (conn, arg1, arg2, arg3, arg4);
462 if (!conn->send ('R'))
464 return marshall (conn, result);
467 template<typename R, typename A1, typename A2, typename A3, typename A4,
470 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
471 A3 arg3, A4 arg4, A5 arg5)
473 if (!conn->send ('Q'))
475 if (!marshall (conn, method))
477 if (!marshall (conn, 5))
479 if (!marshall (conn, arg1))
481 if (!marshall (conn, arg2))
483 if (!marshall (conn, arg3))
485 if (!marshall (conn, arg4))
487 if (!marshall (conn, arg5))
489 if (!conn->wait_for_result ())
491 if (!unmarshall (conn, result))
496 template<typename R, typename A1, typename A2, typename A3, typename A4,
497 typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
499 callback (connection *conn)
501 argument_wrapper<A1> arg1;
502 argument_wrapper<A2> arg2;
503 argument_wrapper<A3> arg3;
504 argument_wrapper<A4> arg4;
505 argument_wrapper<A5> arg5;
508 if (!unmarshall_check (conn, 5))
510 if (!arg1.unmarshall (conn))
512 if (!arg2.unmarshall (conn))
514 if (!arg3.unmarshall (conn))
516 if (!arg4.unmarshall (conn))
518 if (!arg5.unmarshall (conn))
520 result = func (conn, arg1, arg2, arg3, arg4, arg5);
521 if (!conn->send ('R'))
523 return marshall (conn, result);
526 template<typename R, typename A1, typename A2, typename A3, typename A4,
527 typename A5, typename A6, typename A7>
529 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
530 A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
532 if (!conn->send ('Q'))
534 if (!marshall (conn, method))
536 if (!marshall (conn, 7))
538 if (!marshall (conn, arg1))
540 if (!marshall (conn, arg2))
542 if (!marshall (conn, arg3))
544 if (!marshall (conn, arg4))
546 if (!marshall (conn, arg5))
548 if (!marshall (conn, arg6))
550 if (!marshall (conn, arg7))
552 if (!conn->wait_for_result ())
554 if (!unmarshall (conn, result))
559 template<typename R, typename A1, typename A2, typename A3, typename A4,
560 typename A5, typename A6, typename A7,
561 R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>
563 callback (connection *conn)
565 argument_wrapper<A1> arg1;
566 argument_wrapper<A2> arg2;
567 argument_wrapper<A3> arg3;
568 argument_wrapper<A4> arg4;
569 argument_wrapper<A5> arg5;
570 argument_wrapper<A6> arg6;
571 argument_wrapper<A7> arg7;
574 if (!unmarshall_check (conn, 7))
576 if (!arg1.unmarshall (conn))
578 if (!arg2.unmarshall (conn))
580 if (!arg3.unmarshall (conn))
582 if (!arg4.unmarshall (conn))
584 if (!arg5.unmarshall (conn))
586 if (!arg6.unmarshall (conn))
588 if (!arg7.unmarshall (conn))
590 result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
591 if (!conn->send ('R'))
593 return marshall (conn, result);
597 #endif // CC1_PLUGIN_RPC_HH