]> git.ipfire.org Git - thirdparty/gcc.git/blame - libcc1/rpc.hh
libcc1: add more uses of 'deleter'
[thirdparty/gcc.git] / libcc1 / rpc.hh
CommitLineData
ddc8de03 1/* RPC call and callback templates
99dee823 2 Copyright (C) 2014-2021 Free Software Foundation, Inc.
ddc8de03
PM
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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"
ddc8de03 24#include "connection.hh"
0f237df2 25#include "deleter.hh"
ddc8de03
PM
26
27namespace 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
c10a3b13
TT
43 argument_wrapper (const argument_wrapper &) = delete;
44 argument_wrapper &operator= (const argument_wrapper &) = delete;
45
ddc8de03
PM
46 operator T () const { return m_object; }
47
48 status unmarshall (connection *conn)
49 {
50 return ::cc1_plugin::unmarshall (conn, &m_object);
51 }
52
53 private:
54
55 T m_object;
ddc8de03
PM
56 };
57
0d5a0b9a
TT
58 // Specialization for any kind of pointer.
59 template<typename T>
60 class argument_wrapper<T *>
8db29d88
AO
61 {
62 public:
0d5a0b9a
TT
63 argument_wrapper () = default;
64 ~argument_wrapper () = default;
8db29d88 65
c10a3b13
TT
66 argument_wrapper (const argument_wrapper &) = delete;
67 argument_wrapper &operator= (const argument_wrapper &) = delete;
68
0d5a0b9a
TT
69 typedef typename std::remove_const<T>::type type;
70
71 operator const type * () const
8db29d88 72 {
0d5a0b9a 73 return m_object.get ();
8db29d88
AO
74 }
75
76 status unmarshall (connection *conn)
77 {
0d5a0b9a
TT
78 type *ptr;
79 if (!::cc1_plugin::unmarshall (conn, &ptr))
80 return FAIL;
81 m_object.reset (ptr);
82 return OK;
8db29d88
AO
83 }
84
85 private:
86
0f237df2 87 unique_ptr<type> m_object;
8db29d88 88 };
8db29d88 89
ddc8de03 90 // There are two kinds of template functions here: "call" and
dc6be7c0
TT
91 // "callback". "call" is implemented with variadic templates, but
92 // "callback" is repeated multiple times to handle different numbers
93 // of arguments. (This could be improved with C++17 and
94 // std::apply.)
ddc8de03
PM
95
96 // The "call" template is used for making a remote procedure call.
97 // It starts a query ('Q') packet, marshalls its arguments, waits
98 // for a result, and finally reads and returns the result via an
99 // "out" parameter.
100
101 // The "callback" template is used when receiving a remote procedure
102 // call. This template function is suitable for use with the
103 // "callbacks" and "connection" classes. It decodes incoming
104 // arguments, passes them to the wrapped function, and finally
105 // marshalls a reply packet.
106
dc6be7c0 107 template<typename R, typename... Arg>
ddc8de03 108 status
dc6be7c0 109 call (connection *conn, const char *method, R *result, Arg... args)
ddc8de03
PM
110 {
111 if (!conn->send ('Q'))
112 return FAIL;
113 if (!marshall (conn, method))
114 return FAIL;
dc6be7c0
TT
115 if (!marshall (conn, (int) sizeof... (Arg)))
116 return FAIL;
117 if (!marshall (conn, args...))
ddc8de03
PM
118 return FAIL;
119 if (!conn->wait_for_result ())
120 return FAIL;
121 if (!unmarshall (conn, result))
122 return FAIL;
123 return OK;
124 }
125
126 template<typename R, R (*func) (connection *)>
127 status
128 callback (connection *conn)
129 {
130 R result;
131
132 if (!unmarshall_check (conn, 0))
133 return FAIL;
134 result = func (conn);
135 if (!conn->send ('R'))
136 return FAIL;
137 return marshall (conn, result);
138 }
139
ddc8de03
PM
140 template<typename R, typename A, R (*func) (connection *, A)>
141 status
142 callback (connection *conn)
143 {
144 argument_wrapper<A> arg;
145 R result;
146
147 if (!unmarshall_check (conn, 1))
148 return FAIL;
149 if (!arg.unmarshall (conn))
150 return FAIL;
151 result = func (conn, arg);
152 if (!conn->send ('R'))
153 return FAIL;
154 return marshall (conn, result);
155 }
156
ddc8de03
PM
157 template<typename R, typename A1, typename A2, R (*func) (connection *,
158 A1, A2)>
159 status
160 callback (connection *conn)
161 {
162 argument_wrapper<A1> arg1;
163 argument_wrapper<A2> arg2;
164 R result;
165
166 if (!unmarshall_check (conn, 2))
167 return FAIL;
168 if (!arg1.unmarshall (conn))
169 return FAIL;
170 if (!arg2.unmarshall (conn))
171 return FAIL;
172 result = func (conn, arg1, arg2);
173 if (!conn->send ('R'))
174 return FAIL;
175 return marshall (conn, result);
176 }
177
ddc8de03
PM
178 template<typename R, typename A1, typename A2, typename A3,
179 R (*func) (connection *, A1, A2, A3)>
180 status
181 callback (connection *conn)
182 {
183 argument_wrapper<A1> arg1;
184 argument_wrapper<A2> arg2;
185 argument_wrapper<A3> arg3;
186 R result;
187
188 if (!unmarshall_check (conn, 3))
189 return FAIL;
190 if (!arg1.unmarshall (conn))
191 return FAIL;
192 if (!arg2.unmarshall (conn))
193 return FAIL;
194 if (!arg3.unmarshall (conn))
195 return FAIL;
196 result = func (conn, arg1, arg2, arg3);
197 if (!conn->send ('R'))
198 return FAIL;
199 return marshall (conn, result);
200 }
201
ddc8de03
PM
202 template<typename R, typename A1, typename A2, typename A3, typename A4,
203 R (*func) (connection *, A1, A2, A3, A4)>
204 status
205 callback (connection *conn)
206 {
207 argument_wrapper<A1> arg1;
208 argument_wrapper<A2> arg2;
209 argument_wrapper<A3> arg3;
210 argument_wrapper<A4> arg4;
211 R result;
212
213 if (!unmarshall_check (conn, 4))
214 return FAIL;
215 if (!arg1.unmarshall (conn))
216 return FAIL;
217 if (!arg2.unmarshall (conn))
218 return FAIL;
219 if (!arg3.unmarshall (conn))
220 return FAIL;
221 if (!arg4.unmarshall (conn))
222 return FAIL;
223 result = func (conn, arg1, arg2, arg3, arg4);
224 if (!conn->send ('R'))
225 return FAIL;
226 return marshall (conn, result);
227 }
228
ddc8de03
PM
229 template<typename R, typename A1, typename A2, typename A3, typename A4,
230 typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
231 status
232 callback (connection *conn)
233 {
234 argument_wrapper<A1> arg1;
235 argument_wrapper<A2> arg2;
236 argument_wrapper<A3> arg3;
237 argument_wrapper<A4> arg4;
238 argument_wrapper<A5> arg5;
239 R result;
240
241 if (!unmarshall_check (conn, 5))
242 return FAIL;
243 if (!arg1.unmarshall (conn))
244 return FAIL;
245 if (!arg2.unmarshall (conn))
246 return FAIL;
247 if (!arg3.unmarshall (conn))
248 return FAIL;
249 if (!arg4.unmarshall (conn))
250 return FAIL;
251 if (!arg5.unmarshall (conn))
252 return FAIL;
253 result = func (conn, arg1, arg2, arg3, arg4, arg5);
254 if (!conn->send ('R'))
255 return FAIL;
256 return marshall (conn, result);
257 }
258
ddc8de03
PM
259 template<typename R, typename A1, typename A2, typename A3, typename A4,
260 typename A5, typename A6, typename A7,
261 R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>
262 status
263 callback (connection *conn)
264 {
265 argument_wrapper<A1> arg1;
266 argument_wrapper<A2> arg2;
267 argument_wrapper<A3> arg3;
268 argument_wrapper<A4> arg4;
269 argument_wrapper<A5> arg5;
270 argument_wrapper<A6> arg6;
271 argument_wrapper<A7> arg7;
272 R result;
273
274 if (!unmarshall_check (conn, 7))
275 return FAIL;
276 if (!arg1.unmarshall (conn))
277 return FAIL;
278 if (!arg2.unmarshall (conn))
279 return FAIL;
280 if (!arg3.unmarshall (conn))
281 return FAIL;
282 if (!arg4.unmarshall (conn))
283 return FAIL;
284 if (!arg5.unmarshall (conn))
285 return FAIL;
286 if (!arg6.unmarshall (conn))
287 return FAIL;
288 if (!arg7.unmarshall (conn))
289 return FAIL;
290 result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
291 if (!conn->send ('R'))
292 return FAIL;
293 return marshall (conn, result);
294 }
295};
296
297#endif // CC1_PLUGIN_RPC_HH