1/* RPC call and callback templates 2 Copyright (C) 2014 Free Software Foundation, Inc. 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" 24#include "marshall.hh" 25#include "connection.hh" 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 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 487