Merge branch 'vendor/GCC50' - gcc 5.0 snapshot 1 FEB 2015
[dragonfly.git] / contrib / gcc-5.0 / libcc1 / rpc.hh
1 /* RPC call and callback templates
2    Copyright (C) 2014 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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
9 version.
10
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
14 for more details.
15
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/>.  */
19
20 #ifndef CC1_PLUGIN_RPC_HH
21 #define CC1_PLUGIN_RPC_HH
22
23 #include "status.hh"
24 #include "marshall.hh"
25 #include "connection.hh"
26
27 namespace cc1_plugin
28 {
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.
34
35   template<typename T>
36   class argument_wrapper
37   {
38   public:
39
40     argument_wrapper () { }
41     ~argument_wrapper () { }
42
43     operator T () const { return m_object; }
44
45     status unmarshall (connection *conn)
46     {
47       return ::cc1_plugin::unmarshall (conn, &m_object);
48     }
49
50   private:
51
52     T m_object;
53
54     // No copying or assignment allowed.
55     argument_wrapper (const argument_wrapper &);
56     argument_wrapper &operator= (const argument_wrapper &);
57   };
58
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.
62   template<typename T>
63   class argument_wrapper<const T *>;
64
65   // Specialization for string types.
66   template<>
67   class argument_wrapper<const char *>
68   {
69   public:
70     argument_wrapper () : m_object (NULL) { }
71     ~argument_wrapper ()
72     {
73       delete[] m_object;
74     }
75
76     operator const char * () const
77     {
78       return m_object;
79     }
80
81     status unmarshall (connection *conn)
82     {
83       return ::cc1_plugin::unmarshall (conn, &m_object);
84     }
85
86   private:
87
88     char *m_object;
89
90     // No copying or assignment allowed.
91     argument_wrapper (const argument_wrapper &);
92     argument_wrapper &operator= (const argument_wrapper &);
93   };
94
95   // Specialization for gcc_type_array.
96   template<>
97   class argument_wrapper<const gcc_type_array *>
98   {
99   public:
100     argument_wrapper () : m_object (NULL) { }
101     ~argument_wrapper ()
102     {
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;
107       delete m_object;
108     }
109
110     operator const gcc_type_array * () const
111     {
112       return m_object;
113     }
114
115     status unmarshall (connection *conn)
116     {
117       return ::cc1_plugin::unmarshall (conn, &m_object);
118     }
119
120   private:
121
122     gcc_type_array *m_object;
123
124     // No copying or assignment allowed.
125     argument_wrapper (const argument_wrapper &);
126     argument_wrapper &operator= (const argument_wrapper &);
127   };
128
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
133   // used.)
134
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
138   // "out" parameter.
139
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.
145
146   template<typename R>
147   status
148   call (connection *conn, const char *method, R *result)
149   {
150     if (!conn->send ('Q'))
151       return FAIL;
152     if (!marshall (conn, method))
153       return FAIL;
154     if (!marshall (conn, 0))
155       return FAIL;
156     if (!conn->wait_for_result ())
157       return FAIL;
158     if (!unmarshall (conn, result))
159       return FAIL;
160     return OK;
161   }
162
163   template<typename R, R (*func) (connection *)>
164   status
165   callback (connection *conn)
166   {
167     R result;
168
169     if (!unmarshall_check (conn, 0))
170       return FAIL;
171     result = func (conn);
172     if (!conn->send ('R'))
173       return FAIL;
174     return marshall (conn, result);
175   }
176
177   template<typename R, typename A>
178   status
179   call (connection *conn, const char *method, R *result, A arg)
180   {
181     if (!conn->send ('Q'))
182       return FAIL;
183     if (!marshall (conn, method))
184       return FAIL;
185     if (!marshall (conn, 1))
186       return FAIL;
187     if (!marshall (conn, arg))
188       return FAIL;
189     if (!conn->wait_for_result ())
190       return FAIL;
191     if (!unmarshall (conn, result))
192       return FAIL;
193     return OK;
194   }
195
196   template<typename R, typename A, R (*func) (connection *, A)>
197   status
198   callback (connection *conn)
199   {
200     argument_wrapper<A> arg;
201     R result;
202
203     if (!unmarshall_check (conn, 1))
204       return FAIL;
205     if (!arg.unmarshall (conn))
206       return FAIL;
207     result = func (conn, arg);
208     if (!conn->send ('R'))
209       return FAIL;
210     return marshall (conn, result);
211   }
212
213   template<typename R, typename A1, typename A2>
214   status
215   call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
216   {
217     if (!conn->send ('Q'))
218       return FAIL;
219     if (!marshall (conn, method))
220       return FAIL;
221     if (!marshall (conn, 2))
222       return FAIL;
223     if (!marshall (conn, arg1))
224       return FAIL;
225     if (!marshall (conn, arg2))
226       return FAIL;
227     if (!conn->wait_for_result ())
228       return FAIL;
229     if (!unmarshall (conn, result))
230       return FAIL;
231     return OK;
232   }
233
234   template<typename R, typename A1, typename A2, R (*func) (connection *,
235                                                             A1, A2)>
236   status
237   callback (connection *conn)
238   {
239     argument_wrapper<A1> arg1;
240     argument_wrapper<A2> arg2;
241     R result;
242
243     if (!unmarshall_check (conn, 2))
244       return FAIL;
245     if (!arg1.unmarshall (conn))
246       return FAIL;
247     if (!arg2.unmarshall (conn))
248       return FAIL;
249     result = func (conn, arg1, arg2);
250     if (!conn->send ('R'))
251       return FAIL;
252     return marshall (conn, result);
253   }
254
255   template<typename R, typename A1, typename A2, typename A3>
256   status
257   call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
258         A3 arg3)
259   {
260     if (!conn->send ('Q'))
261       return FAIL;
262     if (!marshall (conn, method))
263       return FAIL;
264     if (!marshall (conn, 3))
265       return FAIL;
266     if (!marshall (conn, arg1))
267       return FAIL;
268     if (!marshall (conn, arg2))
269       return FAIL;
270     if (!marshall (conn, arg3))
271       return FAIL;
272     if (!conn->wait_for_result ())
273       return FAIL;
274     if (!unmarshall (conn, result))
275       return FAIL;
276     return OK;
277   }
278
279   template<typename R, typename A1, typename A2, typename A3,
280            R (*func) (connection *, A1, A2, A3)>
281   status
282   callback (connection *conn)
283   {
284     argument_wrapper<A1> arg1;
285     argument_wrapper<A2> arg2;
286     argument_wrapper<A3> arg3;
287     R result;
288
289     if (!unmarshall_check (conn, 3))
290       return FAIL;
291     if (!arg1.unmarshall (conn))
292       return FAIL;
293     if (!arg2.unmarshall (conn))
294       return FAIL;
295     if (!arg3.unmarshall (conn))
296       return FAIL;
297     result = func (conn, arg1, arg2, arg3);
298     if (!conn->send ('R'))
299       return FAIL;
300     return marshall (conn, result);
301   }
302
303   template<typename R, typename A1, typename A2, typename A3, typename A4>
304   status
305   call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
306         A3 arg3, A4 arg4)
307   {
308     if (!conn->send ('Q'))
309       return FAIL;
310     if (!marshall (conn, method))
311       return FAIL;
312     if (!marshall (conn, 4))
313       return FAIL;
314     if (!marshall (conn, arg1))
315       return FAIL;
316     if (!marshall (conn, arg2))
317       return FAIL;
318     if (!marshall (conn, arg3))
319       return FAIL;
320     if (!marshall (conn, arg4))
321       return FAIL;
322     if (!conn->wait_for_result ())
323       return FAIL;
324     if (!unmarshall (conn, result))
325       return FAIL;
326     return OK;
327   }
328
329   template<typename R, typename A1, typename A2, typename A3, typename A4,
330            R (*func) (connection *, A1, A2, A3, A4)>
331   status
332   callback (connection *conn)
333   {
334     argument_wrapper<A1> arg1;
335     argument_wrapper<A2> arg2;
336     argument_wrapper<A3> arg3;
337     argument_wrapper<A4> arg4;
338     R result;
339
340     if (!unmarshall_check (conn, 4))
341       return FAIL;
342     if (!arg1.unmarshall (conn))
343       return FAIL;
344     if (!arg2.unmarshall (conn))
345       return FAIL;
346     if (!arg3.unmarshall (conn))
347       return FAIL;
348     if (!arg4.unmarshall (conn))
349       return FAIL;
350     result = func (conn, arg1, arg2, arg3, arg4);
351     if (!conn->send ('R'))
352       return FAIL;
353     return marshall (conn, result);
354   }
355
356   template<typename R, typename A1, typename A2, typename A3, typename A4,
357            typename A5>
358   status
359   call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
360         A3 arg3, A4 arg4, A5 arg5)
361   {
362     if (!conn->send ('Q'))
363       return FAIL;
364     if (!marshall (conn, method))
365       return FAIL;
366     if (!marshall (conn, 5))
367       return FAIL;
368     if (!marshall (conn, arg1))
369       return FAIL;
370     if (!marshall (conn, arg2))
371       return FAIL;
372     if (!marshall (conn, arg3))
373       return FAIL;
374     if (!marshall (conn, arg4))
375       return FAIL;
376     if (!marshall (conn, arg5))
377       return FAIL;
378     if (!conn->wait_for_result ())
379       return FAIL;
380     if (!unmarshall (conn, result))
381       return FAIL;
382     return OK;
383   }
384
385   template<typename R, typename A1, typename A2, typename A3, typename A4,
386            typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
387   status
388   callback (connection *conn)
389   {
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;
395     R result;
396
397     if (!unmarshall_check (conn, 5))
398       return FAIL;
399     if (!arg1.unmarshall (conn))
400       return FAIL;
401     if (!arg2.unmarshall (conn))
402       return FAIL;
403     if (!arg3.unmarshall (conn))
404       return FAIL;
405     if (!arg4.unmarshall (conn))
406       return FAIL;
407     if (!arg5.unmarshall (conn))
408       return FAIL;
409     result = func (conn, arg1, arg2, arg3, arg4, arg5);
410     if (!conn->send ('R'))
411       return FAIL;
412     return marshall (conn, result);
413   }
414
415   template<typename R, typename A1, typename A2, typename A3, typename A4,
416            typename A5, typename A6, typename A7>
417   status
418   call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
419         A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
420   {
421     if (!conn->send ('Q'))
422       return FAIL;
423     if (!marshall (conn, method))
424       return FAIL;
425     if (!marshall (conn, 7))
426       return FAIL;
427     if (!marshall (conn, arg1))
428       return FAIL;
429     if (!marshall (conn, arg2))
430       return FAIL;
431     if (!marshall (conn, arg3))
432       return FAIL;
433     if (!marshall (conn, arg4))
434       return FAIL;
435     if (!marshall (conn, arg5))
436       return FAIL;
437     if (!marshall (conn, arg6))
438       return FAIL;
439     if (!marshall (conn, arg7))
440       return FAIL;
441     if (!conn->wait_for_result ())
442       return FAIL;
443     if (!unmarshall (conn, result))
444       return FAIL;
445     return OK;
446   }
447
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)>
451   status
452   callback (connection *conn)
453   {
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;
461     R result;
462
463     if (!unmarshall_check (conn, 7))
464       return FAIL;
465     if (!arg1.unmarshall (conn))
466       return FAIL;
467     if (!arg2.unmarshall (conn))
468       return FAIL;
469     if (!arg3.unmarshall (conn))
470       return FAIL;
471     if (!arg4.unmarshall (conn))
472       return FAIL;
473     if (!arg5.unmarshall (conn))
474       return FAIL;
475     if (!arg6.unmarshall (conn))
476       return FAIL;
477     if (!arg7.unmarshall (conn))
478       return FAIL;
479     result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
480     if (!conn->send ('R'))
481       return FAIL;
482     return marshall (conn, result);
483   }
484 };
485
486 #endif // CC1_PLUGIN_RPC_HH