1 /* RPC call and callback templates
2 Copyright (C) 2014 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 "marshall.hh"
25 #include "connection.hh"
29 // The plugin API may contain some "const" method parameters.
30 // However, when unmarshalling we cannot unmarshall into a const
31 // object; and furthermore we want to be able to deallocate pointers
32 // when finished with them. This wrapper class lets us properly
33 // remove the "const" and handle deallocation from pointer types.
36 class argument_wrapper
40 argument_wrapper () { }
41 ~argument_wrapper () { }
43 operator T () const { return m_object
; }
45 status
unmarshall (connection
*conn
)
47 return ::cc1_plugin::unmarshall (conn
, &m_object
);
54 // No copying or assignment allowed.
55 argument_wrapper (const argument_wrapper
&);
56 argument_wrapper
&operator= (const argument_wrapper
&);
59 // Specialization for any kind of pointer. This is declared but not
60 // defined to avoid bugs if a new pointer type is introduced into
61 // the API. Instead you will just get a compilation error.
63 class argument_wrapper
<const T
*>;
65 // Specialization for string types.
67 class argument_wrapper
<const char *>
70 argument_wrapper () : m_object (NULL
) { }
76 operator const char * () const
81 status
unmarshall (connection
*conn
)
83 return ::cc1_plugin::unmarshall (conn
, &m_object
);
90 // No copying or assignment allowed.
91 argument_wrapper (const argument_wrapper
&);
92 argument_wrapper
&operator= (const argument_wrapper
&);
95 // Specialization for gcc_type_array.
97 class argument_wrapper
<const gcc_type_array
*>
100 argument_wrapper () : m_object (NULL
) { }
103 // It would be nicer if gcc_type_array could have a destructor.
104 // But, it is in code shared with gdb and cannot.
105 if (m_object
!= NULL
)
106 delete[] m_object
->elements
;
110 operator const gcc_type_array
* () const
115 status
unmarshall (connection
*conn
)
117 return ::cc1_plugin::unmarshall (conn
, &m_object
);
122 gcc_type_array
*m_object
;
124 // No copying or assignment allowed.
125 argument_wrapper (const argument_wrapper
&);
126 argument_wrapper
&operator= (const argument_wrapper
&);
129 // There are two kinds of template functions here: "call" and
130 // "callback". They are each repeated multiple times to handle
131 // different numbers of arguments. (This would be improved with
132 // C++11, though applying a call is still tricky until C++14 can be
135 // The "call" template is used for making a remote procedure call.
136 // It starts a query ('Q') packet, marshalls its arguments, waits
137 // for a result, and finally reads and returns the result via an
140 // The "callback" template is used when receiving a remote procedure
141 // call. This template function is suitable for use with the
142 // "callbacks" and "connection" classes. It decodes incoming
143 // arguments, passes them to the wrapped function, and finally
144 // marshalls a reply packet.
148 call (connection
*conn
, const char *method
, R
*result
)
150 if (!conn
->send ('Q'))
152 if (!marshall (conn
, method
))
154 if (!marshall (conn
, 0))
156 if (!conn
->wait_for_result ())
158 if (!unmarshall (conn
, result
))
163 template<typename R
, R (*func
) (connection
*)>
165 callback (connection
*conn
)
169 if (!unmarshall_check (conn
, 0))
171 result
= func (conn
);
172 if (!conn
->send ('R'))
174 return marshall (conn
, result
);
177 template<typename R
, typename A
>
179 call (connection
*conn
, const char *method
, R
*result
, A arg
)
181 if (!conn
->send ('Q'))
183 if (!marshall (conn
, method
))
185 if (!marshall (conn
, 1))
187 if (!marshall (conn
, arg
))
189 if (!conn
->wait_for_result ())
191 if (!unmarshall (conn
, result
))
196 template<typename R
, typename A
, R (*func
) (connection
*, A
)>
198 callback (connection
*conn
)
200 argument_wrapper
<A
> arg
;
203 if (!unmarshall_check (conn
, 1))
205 if (!arg
.unmarshall (conn
))
207 result
= func (conn
, arg
);
208 if (!conn
->send ('R'))
210 return marshall (conn
, result
);
213 template<typename R
, typename A1
, typename A2
>
215 call (connection
*conn
, const char *method
, R
*result
, A1 arg1
, A2 arg2
)
217 if (!conn
->send ('Q'))
219 if (!marshall (conn
, method
))
221 if (!marshall (conn
, 2))
223 if (!marshall (conn
, arg1
))
225 if (!marshall (conn
, arg2
))
227 if (!conn
->wait_for_result ())
229 if (!unmarshall (conn
, result
))
234 template<typename R
, typename A1
, typename A2
, R (*func
) (connection
*,
237 callback (connection
*conn
)
239 argument_wrapper
<A1
> arg1
;
240 argument_wrapper
<A2
> arg2
;
243 if (!unmarshall_check (conn
, 2))
245 if (!arg1
.unmarshall (conn
))
247 if (!arg2
.unmarshall (conn
))
249 result
= func (conn
, arg1
, arg2
);
250 if (!conn
->send ('R'))
252 return marshall (conn
, result
);
255 template<typename R
, typename A1
, typename A2
, typename A3
>
257 call (connection
*conn
, const char *method
, R
*result
, A1 arg1
, A2 arg2
,
260 if (!conn
->send ('Q'))
262 if (!marshall (conn
, method
))
264 if (!marshall (conn
, 3))
266 if (!marshall (conn
, arg1
))
268 if (!marshall (conn
, arg2
))
270 if (!marshall (conn
, arg3
))
272 if (!conn
->wait_for_result ())
274 if (!unmarshall (conn
, result
))
279 template<typename R
, typename A1
, typename A2
, typename A3
,
280 R (*func
) (connection
*, A1
, A2
, A3
)>
282 callback (connection
*conn
)
284 argument_wrapper
<A1
> arg1
;
285 argument_wrapper
<A2
> arg2
;
286 argument_wrapper
<A3
> arg3
;
289 if (!unmarshall_check (conn
, 3))
291 if (!arg1
.unmarshall (conn
))
293 if (!arg2
.unmarshall (conn
))
295 if (!arg3
.unmarshall (conn
))
297 result
= func (conn
, arg1
, arg2
, arg3
);
298 if (!conn
->send ('R'))
300 return marshall (conn
, result
);
303 template<typename R
, typename A1
, typename A2
, typename A3
, typename A4
>
305 call (connection
*conn
, const char *method
, R
*result
, A1 arg1
, A2 arg2
,
308 if (!conn
->send ('Q'))
310 if (!marshall (conn
, method
))
312 if (!marshall (conn
, 4))
314 if (!marshall (conn
, arg1
))
316 if (!marshall (conn
, arg2
))
318 if (!marshall (conn
, arg3
))
320 if (!marshall (conn
, arg4
))
322 if (!conn
->wait_for_result ())
324 if (!unmarshall (conn
, result
))
329 template<typename R
, typename A1
, typename A2
, typename A3
, typename A4
,
330 R (*func
) (connection
*, A1
, A2
, A3
, A4
)>
332 callback (connection
*conn
)
334 argument_wrapper
<A1
> arg1
;
335 argument_wrapper
<A2
> arg2
;
336 argument_wrapper
<A3
> arg3
;
337 argument_wrapper
<A4
> arg4
;
340 if (!unmarshall_check (conn
, 4))
342 if (!arg1
.unmarshall (conn
))
344 if (!arg2
.unmarshall (conn
))
346 if (!arg3
.unmarshall (conn
))
348 if (!arg4
.unmarshall (conn
))
350 result
= func (conn
, arg1
, arg2
, arg3
, arg4
);
351 if (!conn
->send ('R'))
353 return marshall (conn
, result
);
356 template<typename R
, typename A1
, typename A2
, typename A3
, typename A4
,
359 call (connection
*conn
, const char *method
, R
*result
, A1 arg1
, A2 arg2
,
360 A3 arg3
, A4 arg4
, A5 arg5
)
362 if (!conn
->send ('Q'))
364 if (!marshall (conn
, method
))
366 if (!marshall (conn
, 5))
368 if (!marshall (conn
, arg1
))
370 if (!marshall (conn
, arg2
))
372 if (!marshall (conn
, arg3
))
374 if (!marshall (conn
, arg4
))
376 if (!marshall (conn
, arg5
))
378 if (!conn
->wait_for_result ())
380 if (!unmarshall (conn
, result
))
385 template<typename R
, typename A1
, typename A2
, typename A3
, typename A4
,
386 typename A5
, R (*func
) (connection
*, A1
, A2
, A3
, A4
, A5
)>
388 callback (connection
*conn
)
390 argument_wrapper
<A1
> arg1
;
391 argument_wrapper
<A2
> arg2
;
392 argument_wrapper
<A3
> arg3
;
393 argument_wrapper
<A4
> arg4
;
394 argument_wrapper
<A5
> arg5
;
397 if (!unmarshall_check (conn
, 5))
399 if (!arg1
.unmarshall (conn
))
401 if (!arg2
.unmarshall (conn
))
403 if (!arg3
.unmarshall (conn
))
405 if (!arg4
.unmarshall (conn
))
407 if (!arg5
.unmarshall (conn
))
409 result
= func (conn
, arg1
, arg2
, arg3
, arg4
, arg5
);
410 if (!conn
->send ('R'))
412 return marshall (conn
, result
);
415 template<typename R
, typename A1
, typename A2
, typename A3
, typename A4
,
416 typename A5
, typename A6
, typename A7
>
418 call (connection
*conn
, const char *method
, R
*result
, A1 arg1
, A2 arg2
,
419 A3 arg3
, A4 arg4
, A5 arg5
, A6 arg6
, A7 arg7
)
421 if (!conn
->send ('Q'))
423 if (!marshall (conn
, method
))
425 if (!marshall (conn
, 7))
427 if (!marshall (conn
, arg1
))
429 if (!marshall (conn
, arg2
))
431 if (!marshall (conn
, arg3
))
433 if (!marshall (conn
, arg4
))
435 if (!marshall (conn
, arg5
))
437 if (!marshall (conn
, arg6
))
439 if (!marshall (conn
, arg7
))
441 if (!conn
->wait_for_result ())
443 if (!unmarshall (conn
, result
))
448 template<typename R
, typename A1
, typename A2
, typename A3
, typename A4
,
449 typename A5
, typename A6
, typename A7
,
450 R (*func
) (connection
*, A1
, A2
, A3
, A4
, A5
, A6
, A7
)>
452 callback (connection
*conn
)
454 argument_wrapper
<A1
> arg1
;
455 argument_wrapper
<A2
> arg2
;
456 argument_wrapper
<A3
> arg3
;
457 argument_wrapper
<A4
> arg4
;
458 argument_wrapper
<A5
> arg5
;
459 argument_wrapper
<A6
> arg6
;
460 argument_wrapper
<A7
> arg7
;
463 if (!unmarshall_check (conn
, 7))
465 if (!arg1
.unmarshall (conn
))
467 if (!arg2
.unmarshall (conn
))
469 if (!arg3
.unmarshall (conn
))
471 if (!arg4
.unmarshall (conn
))
473 if (!arg5
.unmarshall (conn
))
475 if (!arg6
.unmarshall (conn
))
477 if (!arg7
.unmarshall (conn
))
479 result
= func (conn
, arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
);
480 if (!conn
->send ('R'))
482 return marshall (conn
, result
);
486 #endif // CC1_PLUGIN_RPC_HH