├── .gitignore ├── README.md ├── README.txt ├── RobotControlSupport.cxx ├── RobotControlSupport.h ├── RobotControlSupport.hpp ├── USER_QOS_PROFILES.xml ├── common.cxx ├── common.h ├── function_call.cxx ├── function_call.hpp ├── future_adapter.hpp ├── makefile_robot_i86Linux2.6gcc4.4.5 ├── normative ├── RobotControlSupport.h ├── function_call.h ├── request_reply.h └── sample.h ├── request_reply.cxx ├── request_reply.hpp ├── robot-vs2013.sln ├── robot-vs2015.sln ├── robot.idl ├── robot_client-vs2013.vcxproj ├── robot_client-vs2013.vcxproj.filters ├── robot_client-vs2013.vcxproj.user ├── robot_client-vs2015.vcxproj ├── robot_client-vs2015.vcxproj.filters ├── robot_func.cxx ├── robot_reqrep.cxx ├── robot_test.cxx ├── rpc_types.idl ├── unique_data.h └── vendor_dependent.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | *.lib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dds-rpc-cxx 2 | =========== 3 | 4 | RCP over DDS C++ API 5 | 6 | In December 2014, OMG adopted (but not finalized) the RPC-over-DDS specification. The following files are part of the normative specification. 7 | 8 | 1. normative/function_call.h 9 | 2. normative/request_reply.h 10 | 3. normative/sample.h 11 | 4. ./RobotControlSupport.h (shows an example of what's normative in a "Support" class. RobotControl itself is not normative.) 12 | 13 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | README for the dds-rpc-cxx project. 2 | 3 | rtiddsgen robot.idl -D BASIC -D REDEFINE_DDS_TYPES -namespace -language C++ -replace 4 | 5 | rtiddsgen rpc_types.idl -D BASIC -D REDEFINE_DDS_TYPES -namespace -language C++ -replace 6 | 7 | rm -fr robot.cxx robot.h robotSupport.* robotPlugin.* rpc_types.cxx rpc_types.h rpc_typesPlugin.* rpc_typesSupport.* rpc_types_publisher* robot_publisher* rpc_types_subscriber* robot_subscriber* rpc_types-vs2012.sln 8 | -------------------------------------------------------------------------------- /RobotControlSupport.cxx: -------------------------------------------------------------------------------- 1 | #include "RobotControlSupport.h" 2 | 3 | namespace robot { 4 | 5 | RobotControlSupport::Client::Client() 6 | : dds::rpc::ClientEndpoint( 7 | new dds::rpc::details::ClientImpl(), 0) 8 | { 9 | if (!impl_) 10 | throw std::runtime_error("Could not create robot::RobotControl::Client"); 11 | } 12 | 13 | RobotControlSupport::Client::Client( 14 | const dds::rpc::ClientParams & client_params) 15 | : dds::rpc::ClientEndpoint( 16 | new dds::rpc::details::ClientImpl(client_params), 0) 17 | { 18 | if (!impl_) 19 | throw std::runtime_error("Could not create robot::RobotControl::Client"); 20 | } 21 | 22 | /***********************************************/ 23 | /* Sync methods */ 24 | /***********************************************/ 25 | void RobotControlSupport::Client::command(const Command & command) 26 | { 27 | auto impl = static_cast *>(impl_.get()); 28 | return impl->command(command); 29 | } 30 | 31 | float RobotControlSupport::Client::setSpeed(float speed) 32 | { 33 | auto impl = static_cast *>(impl_.get()); 34 | return impl->setSpeed(speed); 35 | } 36 | 37 | float RobotControlSupport::Client::getSpeed() 38 | { 39 | auto impl = static_cast *>(impl_.get()); 40 | return impl->getSpeed(); 41 | } 42 | 43 | void RobotControlSupport::Client::getStatus(Status & status) 44 | { 45 | auto impl = static_cast *>(impl_.get()); 46 | return impl->getStatus(status); 47 | } 48 | 49 | 50 | /***********************************************/ 51 | /* Async methods */ 52 | /***********************************************/ 53 | dds::rpc::future 54 | RobotControlSupport::Client::command_async(const robot::Command & command) 55 | { 56 | auto impl = static_cast *>(impl_.get()); 57 | return impl->command_async(command); 58 | } 59 | 60 | dds::rpc::future 61 | RobotControlSupport::Client::setSpeed_async(float speed) 62 | { 63 | auto impl = static_cast *>(impl_.get()); 64 | return impl->setSpeed_async(speed); 65 | } 66 | 67 | dds::rpc::future 68 | RobotControlSupport::Client::getSpeed_async() 69 | { 70 | auto impl = static_cast *>(impl_.get()); 71 | return impl->getSpeed_async(); 72 | } 73 | 74 | dds::rpc::future 75 | RobotControlSupport::Client::getStatus_async() 76 | { 77 | auto impl = static_cast *>(impl_.get()); 78 | return impl->getStatus_async(); 79 | } 80 | 81 | 82 | } // namespace robot 83 | 84 | 85 | namespace dds { 86 | namespace rpc { 87 | namespace details { 88 | 89 | static dds::SampleIdentity to_rpc_sample_identity(const DDS::SampleIdentity_t & inid) 90 | { 91 | static_assert(sizeof(dds::SampleIdentity) == sizeof(DDS::SampleIdentity_t), 92 | "Sizes of two SampleIdentity don't match!"); 93 | 94 | dds::SampleIdentity outid; 95 | memcpy(&outid, &inid, sizeof(SampleIdentity_t)); 96 | return outid; 97 | } 98 | 99 | rpc::ReplierParams 100 | to_replier_params(const rpc::ServiceParams & service_params) 101 | { 102 | return rpc::ReplierParams() 103 | .domain_participant(service_params.domain_participant()) 104 | .service_name(service_params.service_name()); 105 | } 106 | 107 | Dispatcher::Dispatcher(robot::RobotControl & service_impl) 108 | : robotimpl_(&service_impl), 109 | replier_(to_replier_params(ServiceParams().service_name("RobotControl"))) 110 | { } 111 | 112 | Dispatcher::Dispatcher( 113 | robot::RobotControl & service_impl, 114 | const ServiceParams & service_params) 115 | : robotimpl_(&service_impl), 116 | replier_(to_replier_params(service_params)) 117 | { } 118 | 119 | void Dispatcher::close() 120 | {} 121 | 122 | bool is_command(const Sample & request_sample) 123 | { 124 | return request_sample.data().data._d == robot::RobotControl_command_Hash; 125 | } 126 | 127 | bool is_getSpeed(const Sample & request_sample) 128 | { 129 | return request_sample.data().data._d == robot::RobotControl_getSpeed_Hash; 130 | } 131 | 132 | bool is_setSpeed(const Sample & request_sample) 133 | { 134 | return request_sample.data().data._d == robot::RobotControl_setSpeed_Hash; 135 | } 136 | 137 | bool is_getStatus(const Sample & request_sample) 138 | { 139 | return request_sample.data().data._d == robot::RobotControl_getStatus_Hash; 140 | } 141 | 142 | helper::unique_data do_command( 143 | const Sample & request_sample, 144 | robot::RobotControl * service_impl) 145 | { 146 | helper::unique_data reply; 147 | 148 | service_impl->command(request_sample.data().data._u.command.com); 149 | 150 | reply->data._d = robot::RobotControl_command_Hash; 151 | reply->data._u.command._d = dds::rpc::REMOTE_EX_OK; 152 | reply->data._u.command._u.result.dummy = 0; 153 | 154 | return reply; 155 | } 156 | 157 | helper::unique_data do_setSpeed( 158 | const Sample & request_sample, 159 | robot::RobotControl * service_impl) 160 | { 161 | helper::unique_data reply; 162 | 163 | try 164 | { 165 | float speed = 166 | service_impl->setSpeed(request_sample.data().data._u.setSpeed.speed); 167 | 168 | reply->data._d = robot::RobotControl_setSpeed_Hash; 169 | reply->data._u.setSpeed._d = dds::rpc::REMOTE_EX_OK; 170 | reply->data._u.setSpeed._u.result.return_ = speed; 171 | } 172 | catch (robot::TooFast & toofast) 173 | { 174 | reply->data._d = robot::RobotControl_setSpeed_Hash; 175 | reply->data._u.setSpeed._d = robot::TooFast_Ex_Hash; 176 | reply->data._u.setSpeed._u.toofast_ex = toofast; 177 | } 178 | 179 | return reply; 180 | } 181 | 182 | helper::unique_data do_getSpeed( 183 | const Sample & request_sample, 184 | robot::RobotControl * service_impl) 185 | { 186 | helper::unique_data reply; 187 | 188 | float speed = service_impl->getSpeed(); 189 | 190 | reply->data._d = robot::RobotControl_getSpeed_Hash; 191 | reply->data._u.getSpeed._d = dds::rpc::REMOTE_EX_OK; 192 | reply->data._u.getSpeed._u.result.return_ = speed; 193 | 194 | return reply; 195 | } 196 | 197 | helper::unique_data do_getStatus( 198 | const Sample & request_sample, 199 | robot::RobotControl * service_impl) 200 | { 201 | helper::unique_data reply; 202 | 203 | reply->data._d = robot::RobotControl_getStatus_Hash; 204 | reply->data._u.getStatus._d = dds::rpc::REMOTE_EX_OK; 205 | service_impl->getStatus(reply->data._u.getStatus._u.result.status); 206 | 207 | return reply; 208 | } 209 | 210 | void Dispatcher::dispatch(const dds::Duration & timeout) 211 | { 212 | Sample request_sample; 213 | helper::unique_data reply; 214 | 215 | if (replier_.receive_request(request_sample, timeout)) 216 | { 217 | if (is_command(request_sample)) 218 | reply = do_command(request_sample, robotimpl_); 219 | else if (is_getSpeed(request_sample)) 220 | reply = do_getSpeed(request_sample, robotimpl_); 221 | else if (is_setSpeed(request_sample)) 222 | reply = do_setSpeed(request_sample, robotimpl_); 223 | else if (is_getStatus(request_sample)) 224 | reply = do_getStatus(request_sample, robotimpl_); 225 | else 226 | { 227 | reply->header.remoteEx = dds::rpc::REMOTE_EX_UNKNOWN_OPERATION; 228 | reply->data._d = 0; // default 229 | } 230 | 231 | replier_.send_reply(*reply, to_rpc_sample_identity(request_sample.identity())); 232 | } 233 | else 234 | printf("timeout or invalid sampleinfo. Ignoring...\n"); 235 | } 236 | 237 | void Dispatcher::run_impl(const dds::Duration & timeout) 238 | { 239 | dispatch(timeout); 240 | } 241 | 242 | /***************************************************************************/ 243 | /* ClientImpl */ 244 | /***************************************************************************/ 245 | 246 | static dds::rpc::RequesterParams 247 | to_requester_params(const ClientParams & client_params) 248 | { 249 | return dds::rpc::RequesterParams() 250 | .domain_participant(client_params.domain_participant()) 251 | .service_name(client_params.service_name()); 252 | } 253 | 254 | ClientImpl::ClientImpl() 255 | : params_(dds::rpc::ClientParams().service_name("RobotControl")), 256 | requester_(to_requester_params(params_)) 257 | { } 258 | 259 | ClientImpl::ClientImpl( 260 | const dds::rpc::ClientParams & client_params) 261 | : params_(client_params), 262 | requester_(to_requester_params(params_)) 263 | { } 264 | 265 | void ClientImpl::bind(const std::string & instance_name) 266 | { 267 | requester_.bind(instance_name); 268 | } 269 | 270 | void ClientImpl::unbind() 271 | { 272 | requester_.unbind(); 273 | } 274 | 275 | bool ClientImpl::is_bound() const 276 | { 277 | return requester_.is_bound(); 278 | } 279 | 280 | std::string ClientImpl::get_bound_instance_name() const 281 | { 282 | return requester_.get_bound_instance_name(); 283 | } 284 | 285 | std::vector 286 | ClientImpl::get_discovered_service_instances() const 287 | { 288 | return std::vector(); 289 | } 290 | 291 | void ClientImpl::wait_for_service() 292 | { } 293 | 294 | void ClientImpl::wait_for_service( 295 | const dds::Duration & maxWait) 296 | { } 297 | 298 | void ClientImpl::wait_for_service( 299 | std::string instanceName) 300 | { } 301 | 302 | void ClientImpl::wait_for_service( 303 | const dds::Duration & maxWait, 304 | std::string instanceName) 305 | { } 306 | 307 | void ClientImpl::wait_for_services(int count) 308 | { } 309 | 310 | void ClientImpl::wait_for_services( 311 | const dds::Duration & maxWait, 312 | int count) 313 | { } 314 | 315 | void ClientImpl::wait_for_services( 316 | const std::vector & instanceNames) 317 | { } 318 | 319 | void ClientImpl::wait_for_services( 320 | const dds::Duration & maxWait, 321 | const std::vector & instanceNames) 322 | { } 323 | 324 | future 325 | ClientImpl::wait_for_service_async() 326 | { 327 | return future(); 328 | } 329 | 330 | future 331 | ClientImpl::wait_for_service_async( 332 | std::string instanceName) 333 | { 334 | return future(); 335 | } 336 | 337 | future 338 | ClientImpl::wait_for_services_async( 339 | int count) 340 | { 341 | return future(); 342 | } 343 | 344 | future 345 | ClientImpl::wait_for_services_async( 346 | const std::vector & instanceNames) 347 | { 348 | return future(); 349 | } 350 | 351 | DDS::DataWriter * ClientImpl::get_request_datawriter() const 352 | { 353 | return requester_.get_request_datawriter(); 354 | } 355 | 356 | DDS::DataReader * ClientImpl::get_reply_datareader() const 357 | { 358 | return requester_.get_reply_datareader(); 359 | } 360 | 361 | ClientParams ClientImpl::get_client_params() const 362 | { 363 | return params_; 364 | } 365 | 366 | void ClientImpl::close() 367 | { } 368 | 369 | void ClientImpl::command(const robot::Command & command) 370 | { 371 | helper::unique_data request; 372 | Sample reply_sample; 373 | 374 | request->data._d = robot::RobotControl_command_Hash; 375 | request->data._u.command.com = command; 376 | 377 | requester_.send_request(*request); 378 | requester_.receive_reply(reply_sample, 379 | request->header.requestId, 380 | dds::Duration::from_seconds(20)); 381 | printf("reply received successfully from command %d\n", 382 | reply_sample.data().header.relatedRequestId.sequence_number.low); 383 | } 384 | 385 | float ClientImpl::setSpeed(float speed) 386 | { 387 | helper::unique_data request; 388 | Sample reply_sample; 389 | 390 | request->data._d = robot::RobotControl_setSpeed_Hash; 391 | request->data._u.setSpeed.speed = speed; 392 | 393 | requester_.send_request(*request); 394 | requester_.receive_reply(reply_sample, 395 | request->header.requestId, 396 | dds::Duration::from_seconds(20)); 397 | 398 | if (reply_sample.data().data._d == robot::RobotControl_setSpeed_Hash) 399 | { 400 | printf("reply received successfully from setSpeed %d\n", 401 | reply_sample.data().header.relatedRequestId.sequence_number.low); 402 | 403 | switch (reply_sample.data().data._u.setSpeed._d) 404 | { 405 | case dds::rpc::REMOTE_EX_OK: 406 | { 407 | return reply_sample.data().data._u.setSpeed._u.result.return_; 408 | break; 409 | } 410 | case robot::TooFast_Ex_Hash: 411 | { 412 | throw reply_sample.data().data._u.setSpeed._u.toofast_ex; 413 | break; 414 | } 415 | default: 416 | { 417 | throw std::runtime_error("Received unknown exception from setSpeed."); 418 | break; 419 | } 420 | } 421 | } 422 | else 423 | { 424 | throw std::runtime_error("Received unknown response for setSpeed.\n"); 425 | } 426 | } 427 | 428 | float ClientImpl::getSpeed() 429 | { 430 | helper::unique_data request; 431 | Sample reply_sample; 432 | 433 | request->data._d = robot::RobotControl_getSpeed_Hash; 434 | request->data._u.getSpeed.dummy = 0; 435 | 436 | requester_.send_request(*request); 437 | requester_.receive_reply(reply_sample, 438 | request->header.requestId, 439 | dds::Duration::from_seconds(20)); 440 | 441 | if (reply_sample.data().data._d == robot::RobotControl_getSpeed_Hash) 442 | { 443 | printf("reply received successfully from getSpeed %d\n", 444 | reply_sample.data().header.relatedRequestId.sequence_number.low); 445 | 446 | switch (reply_sample.data().data._u.getSpeed._d) 447 | { 448 | case dds::rpc::REMOTE_EX_OK: 449 | { 450 | return reply_sample.data().data._u.getSpeed._u.result.return_; 451 | break; 452 | } 453 | default: 454 | { 455 | throw std::runtime_error("Received unknown exception from getSpeed."); 456 | break; 457 | } 458 | } 459 | } 460 | else 461 | { 462 | throw std::runtime_error("Received unknown response for getSpeed.\n"); 463 | } 464 | } 465 | 466 | void ClientImpl::getStatus(robot::Status & status) 467 | { 468 | helper::unique_data request; 469 | Sample reply_sample; 470 | 471 | request->data._d = robot::RobotControl_getStatus_Hash; 472 | request->data._u.getStatus.dummy = 0; 473 | 474 | requester_.send_request(*request); 475 | requester_.receive_reply(reply_sample, 476 | request->header.requestId, 477 | dds::Duration::from_seconds(20)); 478 | 479 | if (reply_sample.data().data._d == robot::RobotControl_getStatus_Hash) 480 | { 481 | printf("reply received successfully from getStatus %d\n", 482 | reply_sample.data().header.relatedRequestId.sequence_number.low); 483 | 484 | switch (reply_sample.data().data._u.getSpeed._d) 485 | { 486 | case dds::rpc::REMOTE_EX_OK: 487 | { 488 | robot::Status_copy(&status, &reply_sample.data().data._u.getStatus._u.result.status); 489 | break; 490 | } 491 | default: 492 | { 493 | throw std::runtime_error("Received unknown exception from getStatus."); 494 | break; 495 | } 496 | } 497 | } 498 | else 499 | { 500 | throw std::runtime_error("Received unknown response for getStatus.\n"); 501 | } 502 | } 503 | 504 | dds::rpc::future 505 | ClientImpl::command_async( 506 | const robot::Command & command) 507 | { 508 | helper::unique_data request; 509 | Sample reply_sample; 510 | 511 | request->data._d = robot::RobotControl_command_Hash; 512 | request->data._u.getSpeed.dummy = 0; 513 | 514 | return 515 | requester_ 516 | .send_request_async(*request) 517 | .then([](dds::rpc::future > && reply) { 518 | reply.get(); 519 | }); 520 | } 521 | 522 | dds::rpc::future 523 | ClientImpl::setSpeed_async(float speed) 524 | { 525 | helper::unique_data request; 526 | Sample reply_sample; 527 | 528 | request->data._d = robot::RobotControl_setSpeed_Hash; 529 | request->data._u.setSpeed.speed = speed; 530 | 531 | return 532 | requester_ 533 | .send_request_async(*request) 534 | .then([](dds::rpc::future > && reply_fut) { 535 | Sample reply_sample = reply_fut.get(); 536 | if (reply_sample.data().data._u.setSpeed._d == robot::TooFast_Ex_Hash) 537 | { 538 | throw robot::TooFast(); 539 | } 540 | else 541 | return reply_sample.data().data._u.setSpeed._u.result.return_; 542 | }); 543 | } 544 | 545 | dds::rpc::future 546 | ClientImpl::getSpeed_async() 547 | { 548 | helper::unique_data request; 549 | Sample reply_sample; 550 | 551 | request->data._d = robot::RobotControl_getSpeed_Hash; 552 | request->data._u.getSpeed.dummy = 0; 553 | 554 | return 555 | requester_.send_request_async(*request) 556 | .then([](dds::rpc::future > && reply) { 557 | return reply.get().data().data._u.getSpeed._u.result.return_; 558 | }); 559 | } 560 | 561 | dds::rpc::future 562 | ClientImpl::getStatus_async() 563 | { 564 | helper::unique_data request; 565 | Sample reply_sample; 566 | 567 | request->data._d = robot::RobotControl_getStatus_Hash; 568 | request->data._u.getSpeed.dummy = 0; 569 | 570 | return 571 | requester_.send_request_async(*request) 572 | .then([](dds::rpc::future > && reply_fut) { 573 | return reply_fut.get().data().data._u.getStatus._u.result; 574 | }); 575 | } 576 | 577 | } // namespace details 578 | } // namespace rpc 579 | } // namespace dds 580 | 581 | /* 582 | Client::Client() 583 | : impl_(boost::make_shared()) 584 | {} 585 | 586 | */ -------------------------------------------------------------------------------- /RobotControlSupport.h: -------------------------------------------------------------------------------- 1 | #ifndef ROBOTCONTROL_SUPPORT_H 2 | #define ROBOTCONTROL_SUPPORT_H 3 | 4 | #include "normative/function_call.h" 5 | 6 | #include "robotPlugin.h" 7 | #include "robotSupport.h" 8 | 9 | namespace robot { 10 | 11 | class RobotControlSupport; 12 | class RobotControlAsync; 13 | 14 | class RobotControl 15 | { 16 | public: 17 | 18 | typedef RobotControlAsync AsyncInterfaceType; 19 | typedef RobotControlSupport SupportType; 20 | typedef RobotControl_Request RequestType; 21 | typedef RobotControl_Reply ReplyType; 22 | 23 | virtual void command(const Command & command) = 0; 24 | virtual float setSpeed(float speed) = 0; 25 | virtual float getSpeed() = 0; 26 | virtual void getStatus(Status & status) = 0; 27 | 28 | virtual ~RobotControl() { } 29 | }; 30 | 31 | class RobotControlAsync 32 | { 33 | public: 34 | 35 | typedef RobotControl InterfaceType; 36 | typedef RobotControlSupport SupportType; 37 | typedef RobotControl_Request RequestType; 38 | typedef RobotControl_Reply ReplyType; 39 | 40 | virtual dds::rpc::future command_async(const robot::Command & command) = 0; 41 | virtual dds::rpc::future setSpeed_async(float speed) = 0; 42 | virtual dds::rpc::future getSpeed_async() = 0; 43 | virtual dds::rpc::future getStatus_async() = 0; 44 | 45 | virtual ~RobotControlAsync() { } 46 | }; 47 | 48 | class RobotControlSupport 49 | { 50 | public: 51 | typedef robot::RobotControl InterfaceType; 52 | typedef robot::RobotControlAsync AsyncInterfaceType; 53 | typedef robot::RobotControl_Request RequestType; 54 | typedef robot::RobotControl_Reply ReplyType; 55 | 56 | class Client : public virtual robot::RobotControl, 57 | public virtual robot::RobotControlAsync, 58 | public virtual dds::rpc::ClientEndpoint 59 | { 60 | public: 61 | 62 | Client(); 63 | 64 | Client(const dds::rpc::ClientParams & client_params); 65 | 66 | /* Methods from RobotControl */ 67 | void command(const Command & command); 68 | float setSpeed(float speed); 69 | float getSpeed(); 70 | void getStatus(Status & status); 71 | 72 | /* Methods from RobotControlAsync */ 73 | dds::rpc::future command_async(const robot::Command & command); 74 | dds::rpc::future setSpeed_async(float speed); 75 | dds::rpc::future getSpeed_async(); 76 | dds::rpc::future getStatus_async(); 77 | 78 | }; 79 | 80 | class Service : public dds::rpc::ServiceEndpoint 81 | { 82 | public: 83 | 84 | // Normative: Uses default Server 85 | Service(); 86 | 87 | // Normative: Uses default Server 88 | template 89 | Service(Impl & impl); 90 | 91 | template 92 | Service(Impl & impl, dds::rpc::Server & server); 93 | 94 | template 95 | Service(Impl & impl, 96 | dds::rpc::Server & server, 97 | const dds::rpc::ServiceParams & service_params); 98 | 99 | }; 100 | 101 | }; 102 | 103 | } // namespace robot 104 | 105 | 106 | #include "RobotControlSupport.hpp" 107 | 108 | #endif // ROBOTCONTROL_SUPPORT_H 109 | -------------------------------------------------------------------------------- /RobotControlSupport.hpp: -------------------------------------------------------------------------------- 1 | #include "unique_data.h" 2 | #include "normative/request_reply.h" 3 | 4 | namespace dds { 5 | namespace rpc { 6 | namespace details { 7 | 8 | template <> 9 | class Dispatcher 10 | : public ServiceEndpointImpl 11 | { 12 | public: 13 | typedef robot::RobotControl InterfaceType; 14 | typedef robot::RobotControl::RequestType RequestType; 15 | typedef robot::RobotControl::ReplyType ReplyType; 16 | typedef dds::rpc::Replier Replier; 17 | 18 | private: 19 | robot::RobotControl * robotimpl_; 20 | Replier replier_; 21 | 22 | void dispatch(const dds::Duration &); 23 | 24 | public: 25 | 26 | Dispatcher(robot::RobotControl & service_impl); 27 | Dispatcher(robot::RobotControl & service_impl, 28 | const ServiceParams & params); 29 | 30 | virtual void close() override; 31 | virtual void run_impl(const dds::Duration &) override; 32 | 33 | }; 34 | 35 | template <> 36 | class ClientImpl 37 | : public ClientEndpointImpl, 38 | public robot::RobotControl, 39 | public robot::RobotControlAsync 40 | { 41 | public: 42 | 43 | ClientImpl(); 44 | 45 | ClientImpl(const dds::rpc::ClientParams & client_params); 46 | 47 | void bind(const std::string & instance_name) override; 48 | void unbind() override; 49 | bool is_bound() const override; 50 | std::string get_bound_instance_name() const override; 51 | std::vector get_discovered_service_instances() const override; 52 | 53 | void wait_for_service() override; 54 | void wait_for_service(const dds::Duration & maxWait) override; 55 | 56 | void wait_for_service(std::string instanceName) override; 57 | void wait_for_service(const dds::Duration & maxWait, 58 | std::string instanceName) override; 59 | 60 | void wait_for_services(int count) override; 61 | void wait_for_services(const dds::Duration & maxWait, int count) override; 62 | 63 | void wait_for_services(const std::vector & instanceNames) override; 64 | void wait_for_services(const dds::Duration & maxWait, 65 | const std::vector & instanceNames) override; 66 | 67 | future wait_for_service_async() override; 68 | future wait_for_service_async(std::string instanceName) override; 69 | future wait_for_services_async(int count) override; 70 | future wait_for_services_async(const std::vector & instanceNames) override; 71 | 72 | void close() override; 73 | 74 | /* Methods from ClientEndpointImpl */ 75 | DDS::DataWriter * get_request_datawriter() const; 76 | DDS::DataReader * get_reply_datareader() const; 77 | dds::rpc::ClientParams get_client_params() const override; 78 | 79 | /* methods from RobotControl */ 80 | void command(const robot::Command & command) override; 81 | float setSpeed(float speed) override; 82 | float getSpeed() override; 83 | void getStatus(robot::Status & status) override; 84 | 85 | /* methods from RobotControlAsync */ 86 | dds::rpc::future command_async(const robot::Command & command) override; 87 | dds::rpc::future setSpeed_async(float speed) override; 88 | dds::rpc::future getSpeed_async() override; 89 | dds::rpc::future getStatus_async() override; 90 | 91 | private: 92 | typedef dds::rpc::Requester< 93 | RobotControl::RequestType, 94 | RobotControl::ReplyType> 95 | Requester; 96 | 97 | dds::rpc::ClientParams params_; 98 | Requester requester_; 99 | }; 100 | 101 | } // namespace details 102 | } // namespace rpc 103 | } // namespace dds 104 | 105 | namespace robot { 106 | 107 | template 108 | RobotControlSupport::Service::Service(Impl & impl) 109 | : ServiceEndpoint(new dds::rpc::details::Dispatcher(impl)) 110 | { 111 | // server.get_impl()->register_service(impl_); 112 | } 113 | 114 | template 115 | RobotControlSupport::Service::Service( 116 | Impl & impl, 117 | dds::rpc::Server & server) 118 | : ServiceEndpoint(new dds::rpc::details::Dispatcher( 119 | impl, 120 | dds::rpc::ServiceParams::service_name("RobotControl")), 0) // ignored = server 121 | { 122 | server.get_impl()->register_service(impl_); 123 | } 124 | 125 | template 126 | RobotControlSupport::Service::Service( 127 | Impl & impl, 128 | dds::rpc::Server & server, 129 | const dds::rpc::ServiceParams & service_params) 130 | : ServiceEndpoint(new dds::rpc::details::Dispatcher(impl, service_params), 0) 131 | { 132 | server.get_impl()->register_service(impl_); 133 | } 134 | 135 | } // namespace robot 136 | 137 | -------------------------------------------------------------------------------- /USER_QOS_PROFILES.xml: -------------------------------------------------------------------------------- 1 | 2 | 70 | 73 | 77 | 78 | 79 | 84 | 87 | 88 | 89 | 90 | robotDataWriter 91 | 92 | 93 | 94 | 97 | 400 98 | 400 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | robotDataReader 107 | 108 | 109 | 110 | 111 | 116 | 117 | robotParticipant 118 | robotParticipantRole 119 | 120 | 121 | 10000 122 | 123 | 124 | 125 | 0 126 | 100000000 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | robotDataWriter 137 | 138 | 139 | 140 | 141 | 142 | 143 | robotDataReader 144 | 145 | 146 | 147 | 148 | 153 | 154 | robotParticipant 155 | robotParticipantRole 156 | 157 | 158 | 10000 159 | 160 | 161 | 162 | 0 163 | 100000000 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /common.cxx: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "rpc_types.h" 3 | #include "ndds/ndds_requestreply_cpp.h" 4 | 5 | bool operator < ( 6 | const DDS_SampleIdentity_t & lhs, 7 | const DDS_SampleIdentity_t & rhs) 8 | { 9 | return lhs.sequence_number < rhs.sequence_number; 10 | } 11 | 12 | namespace dds { 13 | 14 | bool operator < ( 15 | const dds::SampleIdentity & lhs, 16 | const dds::SampleIdentity & rhs) 17 | { 18 | return lhs.sequence_number.low < rhs.sequence_number.low; 19 | } 20 | 21 | namespace rpc { 22 | 23 | namespace details { 24 | 25 | DefaultDomainParticipant::DefaultDomainParticipant() 26 | : domainid(0), 27 | participant(0) 28 | { } 29 | 30 | DefaultDomainParticipant & DefaultDomainParticipant::singleton() 31 | { 32 | static DefaultDomainParticipant default_participant; 33 | return default_participant; 34 | } 35 | 36 | DefaultDomainParticipant & DefaultDomainParticipant::set_domainid(int domainid) 37 | { 38 | this->domainid = domainid; 39 | return *this; 40 | } 41 | 42 | DDSDomainParticipant* DefaultDomainParticipant::get() 43 | { 44 | if(!participant) 45 | participant = TheParticipantFactory->create_participant( 46 | domainid, 47 | DDS::PARTICIPANT_QOS_DEFAULT, 48 | NULL /* listener */, 49 | DDS::STATUS_MASK_NONE); 50 | 51 | return participant; 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | #ifndef OMG_DDS_RPC_COMMON_H 2 | #define OMG_DDS_RPC_COMMON_H 3 | 4 | class DDSDomainParticipant; 5 | struct DDS_SampleIdentity_t; 6 | 7 | bool operator < ( 8 | const DDS_SampleIdentity_t & lhs, 9 | const DDS_SampleIdentity_t & rhs); 10 | 11 | namespace dds { 12 | 13 | class SampleIdentity; 14 | 15 | bool operator < ( 16 | const dds::SampleIdentity & lhs, 17 | const dds::SampleIdentity & rhs); 18 | 19 | namespace rpc { 20 | 21 | namespace details { 22 | 23 | class DefaultDomainParticipant 24 | { 25 | int domainid; 26 | DDSDomainParticipant* participant; 27 | DefaultDomainParticipant(); 28 | 29 | public: 30 | static DefaultDomainParticipant & singleton(); 31 | DefaultDomainParticipant & set_domainid(int domainid); 32 | DDSDomainParticipant* get(); 33 | }; 34 | 35 | } // namespace details 36 | } // namespace rpc 37 | } // namespace dds 38 | 39 | #endif // OMG_DDS_RPC_COMMON_H 40 | -------------------------------------------------------------------------------- /function_call.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "normative/function_call.h" 6 | #include "common.h" 7 | #include "boost/make_shared.hpp" 8 | 9 | namespace dds { 10 | namespace rpc { 11 | 12 | namespace details { 13 | 14 | ServerImpl::ServerImpl() 15 | : participant_(dds::rpc::details::DefaultDomainParticipant::singleton().get()) 16 | { 17 | if (!participant_) 18 | throw std::runtime_error("Unable to create participant"); 19 | } 20 | 21 | ServerImpl::ServerImpl(const ServerParams & sp) 22 | : participant_(sp.default_service_params().domain_participant()) 23 | {} 24 | 25 | void ServerImpl::register_service(boost::shared_ptr dispatcher) 26 | { 27 | dispatchers.push_back(dispatcher); 28 | } 29 | 30 | void ServerImpl::close() 31 | {} 32 | 33 | void ServerImpl::run() 34 | { 35 | for (int i = 0; i < dispatchers.size(); i++) 36 | static_cast(dispatchers[i].get())->run_impl(dds::Duration::from_seconds(20)); 37 | } 38 | 39 | void ServerImpl::run(const dds::Duration & timeout) 40 | { 41 | for (int i = 0; i < dispatchers.size(); i++) 42 | static_cast(dispatchers[i].get())->run_impl(timeout); 43 | } 44 | 45 | ServiceEndpointImpl::~ServiceEndpointImpl() 46 | {} 47 | 48 | } // namespace details 49 | 50 | Exception::Exception() 51 | {} 52 | 53 | Exception::Exception(const char *msg) 54 | : std::exception(), 55 | message_(msg) 56 | {} 57 | 58 | Exception::~Exception() throw() 59 | {} 60 | 61 | Server::Server() 62 | : RPCEntity(boost::make_shared(), 0) 63 | {} 64 | 65 | Server::Server(const ServerParams & server_params) 66 | : RPCEntity(boost::make_shared(server_params), 0) 67 | {} 68 | 69 | Server::VendorDependent Server::get_impl() const 70 | { 71 | return boost::dynamic_pointer_cast(impl_); 72 | } 73 | 74 | void Server::run() 75 | { 76 | dynamic_cast(impl_.get())->run(); 77 | } 78 | 79 | void Server::run(const dds::Duration & timeout) 80 | { 81 | dynamic_cast(impl_.get())->run(timeout); 82 | } 83 | 84 | ServerParams::ServerParams() 85 | : impl_(boost::make_shared()) 86 | {} 87 | 88 | ServerParams::ServerParams(const ServerParams & other) 89 | : impl_(boost::make_shared(*other.impl_.get())) 90 | {} 91 | 92 | ServerParams & ServerParams::operator = (const ServerParams & that) 93 | { 94 | impl_ = boost::make_shared(*that.impl_.get()); 95 | return *this; 96 | } 97 | 98 | ServerParams & ServerParams::default_service_params(const ServiceParams & service_params) 99 | { 100 | impl_->default_service_params(service_params); 101 | return *this; 102 | } 103 | 104 | ServiceParams ServerParams::default_service_params() const 105 | { 106 | return impl_->default_service_params(); 107 | } 108 | 109 | ServiceParams::ServiceParams() 110 | : impl_(boost::make_shared()) 111 | {} 112 | 113 | 114 | ServiceParams::ServiceParams(const ServiceParams & other) 115 | : impl_(boost::make_shared(*other.impl_.get())) 116 | {} 117 | 118 | ServiceParams & ServiceParams::operator = (const ServiceParams & that) 119 | { 120 | impl_ = boost::make_shared(*that.impl_.get()); 121 | return *this; 122 | } 123 | 124 | ServiceParams & ServiceParams::service_name(const std::string &service_name) 125 | { 126 | impl_->service_name(service_name); 127 | return *this; 128 | } 129 | 130 | ServiceParams & ServiceParams::instance_name(const std::string &instance_name) 131 | { 132 | impl_->instance_name(instance_name); 133 | return *this; 134 | } 135 | 136 | ServiceParams & ServiceParams::datawriter_qos(dds_entity_traits::DataWriterQos qos) 137 | { 138 | impl_->datawriter_qos(qos); 139 | return *this; 140 | } 141 | 142 | ServiceParams & ServiceParams::datareader_qos(dds_entity_traits::DataReaderQos qos) 143 | { 144 | impl_->datareader_qos(qos); 145 | return *this; 146 | } 147 | 148 | ServiceParams & ServiceParams::publisher(dds_entity_traits::Publisher publisher) 149 | { 150 | impl_->publisher(publisher); 151 | return *this; 152 | } 153 | 154 | ServiceParams & ServiceParams::subscriber(dds_entity_traits::Subscriber subscriber) 155 | { 156 | impl_->subscriber(subscriber); 157 | return *this; 158 | } 159 | 160 | ServiceParams & ServiceParams::domain_participant(dds_entity_traits::DomainParticipant part) 161 | { 162 | impl_->domain_participant(part); 163 | return *this; 164 | } 165 | 166 | std::string ServiceParams::service_name() const 167 | { 168 | return impl_->service_name(); 169 | } 170 | 171 | std::string ServiceParams::instance_name() const 172 | { 173 | return impl_->instance_name(); 174 | } 175 | 176 | std::string ServiceParams::request_topic_name() const 177 | { 178 | return impl_->request_topic_name(); 179 | } 180 | 181 | std::string ServiceParams::reply_topic_name() const 182 | { 183 | return impl_->reply_topic_name(); 184 | } 185 | 186 | dds_entity_traits::DataWriterQos ServiceParams::datawriter_qos() const 187 | { 188 | return impl_->datawriter_qos(); 189 | } 190 | 191 | dds_entity_traits::DataReaderQos ServiceParams::datareader_qos() const 192 | { 193 | return impl_->datareader_qos(); 194 | } 195 | 196 | dds_entity_traits::Publisher ServiceParams::publisher() const 197 | { 198 | return impl_->publisher(); 199 | } 200 | 201 | dds_entity_traits::Subscriber ServiceParams::subscriber() const 202 | { 203 | return impl_->subscriber(); 204 | } 205 | 206 | dds_entity_traits::DomainParticipant ServiceParams::domain_participant() const 207 | { 208 | return impl_->domain_participant(); 209 | } 210 | 211 | ClientParams::ClientParams() 212 | : impl_(boost::make_shared()) 213 | { } 214 | 215 | 216 | ClientParams::ClientParams(const ClientParams & other) 217 | : impl_(boost::make_shared(*other.impl_.get())) 218 | {} 219 | 220 | ClientParams & ClientParams::domain_participant(dds::dds_entity_traits::DomainParticipant participant) 221 | { 222 | impl_->domain_participant(participant); 223 | return *this; 224 | } 225 | 226 | ClientParams & ClientParams::service_name(const std::string &service_name) 227 | { 228 | impl_->service_name(service_name); 229 | return *this; 230 | } 231 | 232 | const std::string & ClientParams::service_name() const 233 | { 234 | return impl_->service_name(); 235 | } 236 | 237 | dds_entity_traits::DomainParticipant ClientParams::domain_participant() const 238 | { 239 | return impl_->domain_participant(); 240 | } 241 | 242 | ClientParams & ClientParams::operator = (const ClientParams & that) 243 | { 244 | impl_ = boost::make_shared(*that.impl_.get()); 245 | return *this; 246 | } 247 | 248 | ServiceEndpoint::ServiceEndpoint(const ServiceEndpoint & se) 249 | : RPCEntity(se) 250 | {} 251 | 252 | ClientEndpoint::ClientEndpoint(const ClientEndpoint & ce) 253 | : ServiceProxy(ce) 254 | {} 255 | 256 | 257 | } // namespace rpc 258 | } // namespace dds 259 | 260 | namespace dds { 261 | 262 | namespace rpc { 263 | 264 | namespace details { 265 | 266 | ClientParamsImpl::ClientParamsImpl() 267 | {} 268 | 269 | ServerParamsImpl::ServerParamsImpl() 270 | {} 271 | 272 | void ServerParamsImpl::default_service_params(const ServiceParams & service_params) 273 | { 274 | service_params_ = service_params; 275 | } 276 | 277 | ServiceParams ServerParamsImpl::default_service_params() const 278 | { 279 | return service_params_; 280 | } 281 | 282 | ServiceParamsImpl::ServiceParamsImpl() 283 | : participant_(0), 284 | publisher_(0), 285 | subscriber_(0), 286 | dwqos_def(false), 287 | drqos_def(false) 288 | {} 289 | 290 | void ServiceParamsImpl::service_name(const std::string &service_name) 291 | { 292 | service_name_ = service_name; 293 | } 294 | 295 | void ServiceParamsImpl::instance_name(const std::string &instance_name) 296 | { 297 | instance_name_ = instance_name; 298 | } 299 | 300 | void ServiceParamsImpl::request_topic_name(const std::string &req_topic) 301 | { 302 | request_topic_name_ = req_topic; 303 | } 304 | 305 | void ServiceParamsImpl::reply_topic_name(const std::string &rep_topic) 306 | { 307 | reply_topic_name_ = rep_topic; 308 | } 309 | 310 | void ServiceParamsImpl::datawriter_qos(const dds_entity_traits::DataWriterQos qos) 311 | { 312 | dwqos_ = *qos; 313 | dwqos_def = true; 314 | } 315 | 316 | void ServiceParamsImpl::datareader_qos(dds_entity_traits::DataReaderQos qos) 317 | { 318 | drqos_ = *qos; 319 | drqos_def = true; 320 | } 321 | 322 | void ServiceParamsImpl::publisher(DDSPublisher *publisher) 323 | { 324 | publisher_ = publisher; 325 | } 326 | 327 | void ServiceParamsImpl::subscriber(DDSSubscriber *subscriber) 328 | { 329 | subscriber_ = subscriber; 330 | } 331 | 332 | void ServiceParamsImpl::domain_participant(DDSDomainParticipant *part) 333 | { 334 | participant_ = part; 335 | } 336 | 337 | const std::string & ServiceParamsImpl::service_name() const 338 | { 339 | return service_name_; 340 | } 341 | 342 | const std::string & ServiceParamsImpl::instance_name() const 343 | { 344 | return instance_name_; 345 | } 346 | 347 | const std::string & ServiceParamsImpl::request_topic_name() const 348 | { 349 | return request_topic_name_; 350 | } 351 | 352 | const std::string & ServiceParamsImpl::reply_topic_name() const 353 | { 354 | return reply_topic_name_; 355 | } 356 | 357 | dds_entity_traits::DataWriterQos ServiceParamsImpl::datawriter_qos() const 358 | { 359 | if (dwqos_def) 360 | return &dwqos_; 361 | else 362 | return 0; 363 | } 364 | 365 | dds_entity_traits::DataReaderQos ServiceParamsImpl::datareader_qos() const 366 | { 367 | if (drqos_def) 368 | return &drqos_; 369 | else 370 | return 0; 371 | } 372 | 373 | DDSPublisher * ServiceParamsImpl::publisher() const 374 | { 375 | return publisher_; 376 | } 377 | 378 | DDSSubscriber * ServiceParamsImpl::subscriber() const 379 | { 380 | return subscriber_; 381 | } 382 | 383 | dds_entity_traits::DomainParticipant ServiceParamsImpl::domain_participant() const 384 | { 385 | return participant_; 386 | } 387 | 388 | 389 | /* 390 | ClientImpl::ClientImpl() 391 | { 392 | participant_ = 393 | TheParticipantFactory->create_participant( 394 | 0, 395 | DDS::PARTICIPANT_QOS_DEFAULT, 396 | NULL , 397 | DDS::STATUS_MASK_NONE); 398 | 399 | if (!participant_) 400 | throw std::runtime_error("Unable to create participant"); 401 | } 402 | 403 | ClientImpl::ClientImpl(dds::DomainParticipant * part, 404 | dds::Publisher * pub, 405 | dds::Subscriber * sub) 406 | : participant_(part), 407 | publisher_(pub), 408 | subscriber_(sub) 409 | { 410 | if (!participant_) 411 | throw std::runtime_error("Null participant"); 412 | } 413 | */ 414 | } // namespace details 415 | 416 | } // namespace rpc 417 | 418 | } // namespace dds 419 | 420 | -------------------------------------------------------------------------------- /function_call.hpp: -------------------------------------------------------------------------------- 1 | #include "normative/request_reply.h" 2 | 3 | namespace dds { 4 | namespace rpc { 5 | namespace details { 6 | 7 | template 8 | class Dispatcher; 9 | 10 | class ServiceEndpointImpl : public RPCEntityImpl 11 | { 12 | public: 13 | 14 | virtual void run_impl(const dds::Duration &) = 0; 15 | virtual ~ServiceEndpointImpl(); 16 | }; 17 | 18 | class ServerImpl : public RPCEntityImpl 19 | { 20 | public: 21 | 22 | std::vector> dispatchers; 23 | DDSDomainParticipant * participant_; 24 | 25 | public: 26 | ServerImpl(); 27 | 28 | ServerImpl(const ServerParams & server_params); 29 | 30 | void register_service(boost::shared_ptr dispatcher); 31 | void run(); 32 | void run(const dds::Duration &); 33 | void close() override; 34 | }; 35 | 36 | class ServiceParamsImpl 37 | { 38 | private: 39 | DDSDomainParticipant * participant_; 40 | DDSPublisher * publisher_; 41 | DDSSubscriber * subscriber_; 42 | DDS_DataWriterQos dwqos_; bool dwqos_def; 43 | DDS_DataReaderQos drqos_; bool drqos_def; 44 | 45 | std::string service_name_; 46 | std::string instance_name_; 47 | std::string request_topic_name_; 48 | std::string reply_topic_name_; 49 | 50 | public: 51 | ServiceParamsImpl(); 52 | 53 | void service_name(const std::string &service_name); 54 | void instance_name(const std::string &instance_name); 55 | void request_topic_name(const std::string &req_topic); 56 | void reply_topic_name(const std::string &rep_topic); 57 | void datawriter_qos(const dds_entity_traits::DataWriterQos qos); 58 | void datareader_qos(const dds_entity_traits::DataReaderQos qos); 59 | void publisher(DDSPublisher *publisher); 60 | void subscriber(DDSSubscriber *subscriber); 61 | void domain_participant(DDSDomainParticipant *part); 62 | 63 | const std::string & service_name() const; 64 | const std::string & instance_name() const; 65 | const std::string & request_topic_name() const; 66 | const std::string & reply_topic_name() const; 67 | dds_entity_traits::DataWriterQos datawriter_qos() const; 68 | dds_entity_traits::DataReaderQos datareader_qos() const; 69 | DDSPublisher * publisher() const; 70 | DDSSubscriber * subscriber() const; 71 | DDSDomainParticipant * domain_participant() const; 72 | }; 73 | 74 | class ClientParamsImpl : public ServiceParamsImpl 75 | { 76 | 77 | public: 78 | ClientParamsImpl(); 79 | }; 80 | 81 | class ServerParamsImpl 82 | { 83 | dds::rpc::ServiceParams service_params_; 84 | 85 | public: 86 | ServerParamsImpl(); 87 | 88 | void default_service_params(const ServiceParams & service_params); 89 | 90 | ServiceParams default_service_params() const; 91 | }; 92 | 93 | 94 | } // namespace details 95 | } // namespace rpc 96 | } // namespace dds 97 | 98 | namespace dds { 99 | 100 | namespace rpc { 101 | 102 | namespace details { 103 | 104 | class ClientEndpointImpl : public ServiceProxyImpl 105 | { 106 | protected: 107 | virtual DDS::DataWriter * get_request_datawriter() const = 0; 108 | virtual DDS::DataReader * get_reply_datareader() const = 0; 109 | 110 | public: 111 | template 112 | typename dds_type_traits::DataWriter get_request_datawriter() const 113 | { 114 | return 115 | static_cast ::DataWriter> 116 | (get_request_datawriter()); // this is a polymorphic dispatch 117 | } 118 | 119 | template 120 | typename dds_type_traits::DataReader get_reply_datareader() const 121 | { 122 | return 123 | static_cast ::DataReader> 124 | (get_reply_datareader()); // this is a polymorphic dispatch 125 | } 126 | 127 | virtual dds::rpc::ClientParams get_client_params() const = 0; 128 | 129 | }; 130 | 131 | } // namespace details 132 | 133 | 134 | } // namespace rpc 135 | } // namespace dds 136 | 137 | namespace dds { 138 | namespace rpc { 139 | 140 | template 141 | ServiceEndpoint::ServiceEndpoint(Impl impl, int) 142 | : RPCEntity(impl, 0) 143 | { } 144 | 145 | template 146 | ClientEndpoint::ClientEndpoint(Impl impl, int) 147 | : ServiceProxy(impl, 0) 148 | { } 149 | 150 | template 151 | typename dds::dds_type_traits::DataWriter 152 | ClientEndpoint::get_request_datawriter() const 153 | { 154 | auto client_endpoint_impl = 155 | static_cast (impl_.get()); 156 | 157 | return client_endpoint_impl->get_request_datawriter(); 158 | } 159 | 160 | template 161 | typename dds::dds_type_traits::DataReader 162 | ClientEndpoint::get_reply_datareader() const 163 | { 164 | auto client_endpoint_impl = 165 | static_cast (impl_.get()); 166 | 167 | return client_endpoint_impl->get_request_datawriter(); 168 | } 169 | 170 | } // namespace rpc 171 | } // namespace dds 172 | 173 | /* 174 | 175 | template 176 | ServiceHandle ServerImpl::register_service( 177 | ServiceImpl &service_impl, 178 | const std::string service_name) 179 | { 180 | auto shptr = 181 | boost::make_shared < 182 | details::Dispatcher> 183 | (service_impl); 184 | 185 | shptr->get_service_impl()->set_service_params( 186 | ServiceParams() 187 | .domain_participant(this->participant_) 188 | .service_name(service_name)); 189 | 190 | dispatchers.push_back(shptr); 191 | 192 | return ServiceHandle(boost::make_shared(0, this)); 193 | } 194 | */ 195 | 196 | /* 197 | template 198 | typename Iface::ProxyType 199 | ClientImpl::resolve_service(const std::string & service_name) 200 | { 201 | return ServiceProxy( 202 | boost::make_shared >( 203 | this, 204 | ServiceParams().domain_participant(participant_) 205 | .service_name(service_name))); 206 | } 207 | */ 208 | -------------------------------------------------------------------------------- /future_adapter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef USE_BOOST_FUTURE 4 | 5 | #define BOOST_THREAD_PROVIDES_FUTURE 6 | #define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION 7 | #define BOOST_RESULT_OF_USE_DECLTYPE 8 | 9 | #include "boost/thread/future.hpp" 10 | #include 11 | 12 | namespace boost { 13 | 14 | template 15 | bool await_ready(future const & t) 16 | { 17 | return t.is_ready(); 18 | } 19 | 20 | template 21 | void await_suspend(future & t, Callback resume) 22 | { 23 | t.then([resume](future const &) 24 | { 25 | resume(); 26 | }); 27 | } 28 | 29 | template 30 | T await_resume(future & t) 31 | { 32 | return t.get(); 33 | } 34 | 35 | } // namespace boost 36 | 37 | namespace std { 38 | namespace experimental { 39 | 40 | template 41 | struct coroutine_traits, Args...> 42 | { 43 | struct promise_type 44 | { 45 | boost::promise promise; 46 | 47 | boost::future get_return_object() { return promise.get_future(); } 48 | bool initial_suspend() { return false; } 49 | bool final_suspend() { return false; } 50 | 51 | void set_exception(std::exception_ptr e) { 52 | promise.set_exception(std::move(e)); 53 | } 54 | /* 55 | void set_result(T & t) { 56 | promise.set_value(t); 57 | } 58 | void set_result(T && t) { 59 | promise.set_value(std::move(t)); 60 | } 61 | */ 62 | void return_value(T & t) { 63 | promise.set_value(t); 64 | } 65 | void return_value(T && t) { 66 | promise.set_value(std::move(t)); 67 | } 68 | }; 69 | }; 70 | 71 | template 72 | struct coroutine_traits, Args...> 73 | { 74 | struct promise_type 75 | { 76 | boost::promise promise; 77 | 78 | boost::future get_return_object() { return promise.get_future(); } 79 | bool initial_suspend() { return false; } 80 | bool final_suspend() { return false; } 81 | 82 | void set_exception(std::exception_ptr e) { 83 | promise.set_exception(std::move(e)); 84 | } 85 | /* 86 | void set_result() { 87 | promise.set_value(); 88 | } 89 | */ 90 | void return_void() { 91 | promise.set_value(); 92 | } 93 | }; 94 | }; 95 | 96 | } // namespace experimental 97 | } // namespace std 98 | 99 | #endif 100 | 101 | #ifdef USE_PPLTASKS 102 | 103 | #include 104 | 105 | #ifdef USE_AWAIT 106 | #include 107 | #endif // USE_AWAIT 108 | 109 | #define BOOST_RESULT_OF_USE_DECLTYPE 110 | 111 | #include "boost/utility/result_of.hpp" 112 | 113 | #endif // USE_PPLTASKS 114 | 115 | namespace dds { 116 | namespace rpc { 117 | 118 | #ifdef USE_BOOST_FUTURE 119 | 120 | // Pull future from boost into this namespace. 121 | using boost::future; 122 | 123 | namespace details { 124 | 125 | template 126 | boost::future> make_ready_future(T&& t) 127 | { 128 | typename std::experimental::coroutine_traits>>::promise_type promise; 129 | future> fut = promise.get_return_object(); 130 | promise.return_value(std::forward(t)); 131 | return fut; 132 | } 133 | 134 | } // namespace details 135 | #endif 136 | 137 | #ifdef USE_PPLTASKS 138 | 139 | namespace details { 140 | 141 | template 142 | class promise; 143 | 144 | } // namespace details 145 | 146 | using concurrency::task; 147 | 148 | template 149 | class future; 150 | 151 | template 152 | class shared_future 153 | { 154 | boost::shared_ptr> shfut_; 155 | 156 | public: 157 | 158 | explicit shared_future(future && fut); 159 | 160 | explicit shared_future(future & fut); 161 | }; 162 | 163 | template 164 | class future 165 | { 166 | task task_; 167 | 168 | public: 169 | 170 | typedef dds::rpc::details::promise promise_type; 171 | typedef ResultType value_type; 172 | 173 | future(); 174 | future(future && other); 175 | future& operator=(future && other); 176 | 177 | future(const future & rhs) = delete; 178 | future& operator=(const future & rhs) = delete; 179 | 180 | task to_task(); 181 | future(const task & task); 182 | future(task && task); 183 | 184 | template 185 | typename details::Unwrapper &&)>::type>::type>::return_type 186 | then(F&& func); 187 | 188 | template 189 | typename details::Unwrapper &&)>::type>::type>::return_type 190 | then(const F & func); 191 | 192 | shared_future share(); 193 | void swap(future& other); 194 | ResultType get(); 195 | bool has_exception() const; 196 | bool has_value() const; 197 | bool is_ready() const; 198 | 199 | void wait() const; 200 | 201 | template 202 | void wait(const Duration &); 203 | }; 204 | 205 | 206 | #endif // USE_PPLTASKS 207 | 208 | } // namespace rpc 209 | } // namespace dds 210 | 211 | 212 | namespace dds { 213 | namespace rpc { 214 | 215 | #ifdef USE_PPLTASKS 216 | 217 | using concurrency::task; 218 | 219 | template 220 | shared_future::shared_future(future && fut) 221 | : shfut_(boost::make_shared>(std::move(fut))) 222 | {} 223 | 224 | namespace details 225 | { 226 | 227 | // Unwrapper adapts lambdas passed to .then function such that the return 228 | // type of the lambda is something PPL Task library can understand. 229 | // There are two cases: 230 | // (1) If the return type of the lambda is anything but 231 | // rpc::future, unwrapping is basically a no-op. I.e., unwrap 232 | // just forwards the closure to the underlying .then(). This includes 233 | // types like int, float, and even task. It works because PPL task 234 | // library knows how to handle lambdas that return task. 235 | // (2) If the return type of the lambda is rpc::future, 236 | // Unwrapper>::task_extractor is a lambda adapter that extracts 237 | // the task out from it so that the PPL task library does not 238 | // create a ridiculous type like task> when we want 239 | // just rpc::future. Note that PPL task library has no knowledge 240 | // of rpc::future. 241 | template 242 | struct Unwrapper 243 | { 244 | typedef future return_type; 245 | 246 | template 247 | static return_type unwrap(Task & task, F&& func) 248 | { 249 | return task.then(std::forward(func)); 250 | } 251 | }; 252 | 253 | template 254 | struct Unwrapper> 255 | { 256 | typedef future return_type; 257 | 258 | template 259 | static return_type unwrap(Task & task, F&& func) 260 | { 261 | return task.then(std::forward(func)); 262 | } 263 | }; 264 | 265 | template 266 | struct Unwrapper> 267 | { 268 | typedef future return_type; 269 | 270 | template 271 | class task_extractor 272 | { 273 | Func func; 274 | 275 | public: 276 | explicit task_extractor(Func && f) 277 | : func(std::move(f)) 278 | {} 279 | 280 | explicit task_extractor(const Func & f) 281 | : func(f) 282 | {} 283 | 284 | template 285 | Task operator ()(Arg&& arg) const { 286 | return func(std::forward(arg)).to_task(); 287 | } 288 | 289 | template 290 | Task operator ()(Arg&& arg) { 291 | return func(std::forward(arg)).to_task(); 292 | } 293 | }; 294 | 295 | template 296 | static return_type unwrap(Task & t, F&& func) 297 | { 298 | return t.then(task_extractor>(std::forward(func))); 299 | } 300 | }; 301 | 302 | } // namespace details 303 | 304 | template 305 | future::future() 306 | : task_() {} 307 | 308 | template 309 | future::future(future && other) 310 | : task_(std::move(other.task_)) 311 | { } 312 | 313 | template 314 | future & future::operator = (future && other) 315 | { 316 | task_ = std::move(other.task_); 317 | return *this; 318 | } 319 | 320 | template 321 | shared_future future::share() 322 | { 323 | return std::move(*this); 324 | } 325 | 326 | template 327 | task future::to_task() 328 | { 329 | return std::move(task_); 330 | } 331 | 332 | template 333 | future::future(const task & task) 334 | : task_(task) 335 | {} 336 | 337 | template 338 | future::future(task && task) 339 | : task_(std::move(task)) 340 | {} 341 | 342 | template 343 | template 344 | typename details::Unwrapper &&)>::type>::type>::return_type 345 | future::then(F&& func) 346 | { 347 | typedef typename std::decay::type>::type FRetType; 348 | return details::Unwrapper::unwrap(task_, std::forward(func)); 349 | } 350 | 351 | template 352 | template 353 | typename details::Unwrapper &&)>::type>::type>::return_type 354 | future::then(const F & func) 355 | { 356 | typedef typename std::decay::type>::type FRetType; 357 | return details::Unwrapper::unwrap(task_, func); 358 | } 359 | 360 | /* // original implementation 361 | template 362 | future::type> 363 | then(const F & func) 364 | { 365 | return task_.then(func); 366 | } 367 | */ 368 | 369 | template 370 | void future::swap(future& other) 371 | { 372 | using std::swap; 373 | swap(task_, other.task_); 374 | } 375 | 376 | template 377 | ResultType future::get() 378 | { 379 | return task_.get(); 380 | } 381 | 382 | template 383 | void future::wait() const 384 | { 385 | task_.wait(); 386 | } 387 | 388 | template 389 | bool future::is_ready() const 390 | { 391 | return task_.is_done(); 392 | } 393 | 394 | template 395 | bool await_ready(future const & t) 396 | { 397 | return t.is_ready(); 398 | } 399 | 400 | template 401 | void await_suspend(future & t, Callback resume) 402 | { 403 | t.then([resume](future const &) 404 | { 405 | resume(); 406 | }); 407 | } 408 | 409 | template 410 | T await_resume(future & t) 411 | { 412 | return t.get(); 413 | } 414 | 415 | #endif // USE_PPLTASKS 416 | 417 | namespace details 418 | { 419 | 420 | #ifdef USE_BOOST_FUTURE 421 | 422 | using boost::promise; 423 | 424 | #endif 425 | 426 | #ifdef USE_PPLTASKS 427 | 428 | using concurrency::task_completion_event; 429 | 430 | template 431 | future> make_ready_future(T&& t) 432 | { 433 | details::promise> promise; 434 | future> fut = promise.get_future(); 435 | promise.set_result(std::forward(t)); 436 | return fut; 437 | } 438 | 439 | template 440 | class promise 441 | { 442 | task_completion_event tce_; 443 | 444 | public: 445 | 446 | future get_future() const { 447 | return future(task(tce_)); 448 | } 449 | 450 | void set_value(ResultType & result) const { 451 | tce_.set(result); 452 | } 453 | 454 | bool set_exception(std::exception_ptr exptr) const { 455 | return tce_.set_exception(std::move(exptr)); 456 | } 457 | 458 | promise& operator = (promise&& other) { 459 | tce_ = std::move(other.tce_); 460 | return *this; 461 | } 462 | promise& operator = (const promise& rhs) = delete; 463 | 464 | void swap(promise & p2) { 465 | using std::swap; 466 | swap(tce_, p2.tce_); 467 | } 468 | 469 | /* await-compatibility functions */ 470 | future get_return_object() { return get_future(); } 471 | bool initial_suspend() { return false; } 472 | bool final_suspend() { return false; } 473 | void set_result(ResultType & t) { 474 | tce_.set(t); 475 | } 476 | void set_result(ResultType && t) { 477 | tce_.set(std::move(t)); 478 | } 479 | void return_value(ResultType & t) { 480 | tce_.set(t); 481 | } 482 | void return_value(ResultType && t) { 483 | tce_.set(std::move(t)); 484 | } 485 | }; 486 | 487 | template <> 488 | class promise 489 | { 490 | task_completion_event tce_; 491 | 492 | public: 493 | 494 | future get_future() const { 495 | return future(task(tce_)); 496 | } 497 | 498 | void set_value() const { 499 | tce_.set(); 500 | } 501 | 502 | bool set_exception(std::exception_ptr exptr) const { 503 | return tce_.set_exception(std::move(exptr)); 504 | } 505 | 506 | promise& operator = (promise&& other) { 507 | tce_ = std::move(other.tce_); 508 | return *this; 509 | } 510 | promise& operator = (const promise& rhs) = delete; 511 | 512 | void swap(promise & p2) { 513 | using std::swap; 514 | swap(tce_, p2.tce_); 515 | } 516 | 517 | /* await-compatibility functions */ 518 | future get_return_object() { return get_future(); } 519 | bool initial_suspend() { return false; } 520 | bool final_suspend() { return false; } 521 | void set_result() { set_value(); } 522 | void return_void() { set_value(); } 523 | }; 524 | 525 | #endif // USE_PPLTASKS 526 | 527 | } // namespace details 528 | } // namespace rpc 529 | } // namespace dds 530 | -------------------------------------------------------------------------------- /makefile_robot_i86Linux2.6gcc4.4.5: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # makefile_robot_i86Linux2.6gcc4.4.5 3 | # 4 | # (c) Copyright, Real-Time Innovations, 2012. All rights reserved. 5 | # No duplications, whole or partial, manual or electronic, may be made 6 | # without express written permission. Any such copies, or 7 | # revisions thereof, must display this notice unaltered. 8 | # This code contains trade secrets of Real-Time Innovations, Inc. 9 | # 10 | # 11 | # This makefile was automatically generated by rtiddsgen. 12 | # 13 | # To compile, type: 14 | # gmake -f makefile_robot_i86Linux2.6gcc4.4.5 15 | # 16 | # Note: This makefile is only meant to build our example applications and 17 | # may require alterations to build on your system. 18 | # 19 | # This makefile assumes that your build environment is already correctly 20 | # configured. (For example, the correct version of your compiler and 21 | # linker should be on your PATH.) 22 | ###################################################################### 23 | 24 | 25 | ############################################################################### 26 | # Ensure $BOOSTHOME is defined 27 | ############################################################################### 28 | ifeq ($(BOOSTHOME), ) 29 | all: 30 | @echo "***************************************************************" 31 | @echo "The environment variable 'BOOSTHOME' is not set!" 32 | @echo "To use this makefile you need to set BOOSTHOME to the directory" 33 | @echo "where you have Boost Libraries installed." 34 | @echo "***************************************************************" 35 | @false 36 | endif 37 | 38 | ifeq ($(CXX), clang++) 39 | CXXFLAGS = -m32 -std=c++0x \ 40 | -Wno-return-type-c-linkage \ 41 | -Wno-deprecated-register 42 | else 43 | CXXFLAGS = -m32 -std=c++0x 44 | endif 45 | 46 | CXX = colorgcc 47 | CXXLD = g++ 48 | CXXLDFLAGS = -m32 -static-libgcc 49 | syslibs_i86Linux2.6gcc4.4.5 = -ldl -lnsl -lm -lpthread -lrt 50 | DEFINES_ARCH_SPECIFIC = -DRTI_UNIX -DRTI_LINUX -DUSE_RTI_CONNEXT \ 51 | -DUSE_BOOST_FUTURE \ 52 | -DUSE_OPTIONAL_RPC_API\ 53 | -DOMG_DDS_RPC_REFERENCE_IMPLEMENTATION\ 54 | -DOMG_DDS_RPC_BASIC_PROFILE \ 55 | -Doverride= 56 | 57 | DEFINES = $(DEFINES_ARCH_SPECIFIC) $(cxx_DEFINES_ARCH_SPECIFIC) 58 | 59 | INCLUDES = -I. -I$(NDDSHOME)/include -I$(NDDSHOME)/include/ndds\ 60 | -I$(BOOSTHOME) 61 | 62 | LIBS = -L$(NDDSHOME)/lib/i86Linux2.6gcc4.4.5 \ 63 | -L$(BOOSTHOME)/stage/lib \ 64 | -l rticonnextmsgcppz -lnddscppz -lnddscz \ 65 | -lnddscorez $(syslibs_i86Linux2.6gcc4.4.5) \ 66 | -lboost_thread -lboost_system 67 | 68 | CDRSOURCES = robot.idl 69 | COMMONSOURCES = common.cxx \ 70 | function_call.cxx \ 71 | request_reply.cxx \ 72 | RobotControlSupport.cxx \ 73 | robot_func.cxx \ 74 | robot_reqrep.cxx \ 75 | robot.cxx \ 76 | robotPlugin.cxx \ 77 | robotSupport.cxx \ 78 | rpc_types.cxx \ 79 | rpc_typesSupport.cxx \ 80 | rpc_typesPlugin.cxx 81 | EXEC = robot_test 82 | DIRECTORIES = objs.dir objs/i86Linux2.6gcc4.4.5.dir 83 | COMMONOBJS = $(COMMONSOURCES:%.cxx=objs/i86Linux2.6gcc4.4.5/%.o) 84 | 85 | # We actually stick the objects in a sub directory to keep your directory clean. 86 | i86Linux2.6gcc4.4.5 : $(DIRECTORIES) $(COMMONOBJS) \ 87 | $(EXEC:%=objs/i86Linux2.6gcc4.4.5/%.o) \ 88 | $(EXEC:%=objs/i86Linux2.6gcc4.4.5/%.out) 89 | 90 | objs/i86Linux2.6gcc4.4.5/%.out : objs/i86Linux2.6gcc4.4.5/%.o 91 | $(CXXLD) $(CXXLDFLAGS) -o $(@:%.out=%) $(@:%.out=%.o) $(COMMONOBJS) $(LIBS) 92 | 93 | objs/i86Linux2.6gcc4.4.5/%.o : %.cxx robot.h 94 | $(CXX) $(CXXFLAGS) -o $@ $(DEFINES) $(INCLUDES) -c $< 95 | 96 | # 97 | # Uncomment these lines if you want the support files regenerated when idl 98 | # file is modified 99 | # 100 | #robot.cxx robot.h \ 101 | #robotPlugin.cxx robotPlugin.h \ 102 | #robotSupport.cxx robotSupport.h : \ 103 | # robot.idl 104 | # $(NDDSHOME)/scripts/rtiddsgen robot.idl -replace 105 | 106 | # Here is how we create those subdirectories automatically. 107 | %.dir : 108 | @echo "Checking directory $*" 109 | @if [ ! -d $* ]; then \ 110 | echo "Making directory $*"; \ 111 | mkdir -p $* ; \ 112 | fi; 113 | -------------------------------------------------------------------------------- /normative/RobotControlSupport.h: -------------------------------------------------------------------------------- 1 | #ifndef ROBOTCONTROL_SUPPORT_H 2 | #define ROBOTCONTROL_SUPPORT_H 3 | 4 | #include "function_call.h" 5 | 6 | #include "robotPlugin.h" 7 | #include "robotSupport.h" 8 | 9 | namespace robot { 10 | 11 | class RobotControlSupport; 12 | class RobotControlAsync; 13 | 14 | class RobotControl 15 | { 16 | public: 17 | 18 | typedef RobotControlAsync AsyncInterfaceType; 19 | typedef RobotControlSupport SupportType; 20 | typedef RobotControl_Request RequestType; 21 | typedef RobotControl_Reply ReplyType; 22 | 23 | virtual void command(const Command & command) = 0; 24 | virtual float setSpeed(float speed) = 0; 25 | virtual float getSpeed() = 0; 26 | virtual void getStatus(Status & status) = 0; 27 | 28 | virtual ~RobotControl() { } 29 | }; 30 | 31 | class RobotControlAsync 32 | { 33 | public: 34 | 35 | typedef RobotControl InterfaceType; 36 | typedef RobotControlSupport SupportType; 37 | typedef RobotControl_Request RequestType; 38 | typedef RobotControl_Reply ReplyType; 39 | 40 | virtual dds::rpc::future command_async(const robot::Command & command) = 0; 41 | virtual dds::rpc::future setSpeed_async(float speed) = 0; 42 | virtual dds::rpc::future getSpeed_async() = 0; 43 | virtual dds::rpc::future getStatus_async() = 0; 44 | 45 | virtual ~RobotControlAsync() { } 46 | }; 47 | 48 | class RobotControlSupport 49 | { 50 | public: 51 | typedef robot::RobotControl InterfaceType; 52 | typedef robot::RobotControlAsync AsyncInterfaceType; 53 | typedef robot::RobotControl_Request RequestType; 54 | typedef robot::RobotControl_Reply ReplyType; 55 | 56 | class Client : public virtual robot::RobotControl, 57 | public virtual robot::RobotControlAsync, 58 | public virtual dds::rpc::ClientEndpoint 59 | { 60 | public: 61 | 62 | Client(); 63 | 64 | Client(const dds::rpc::ClientParams & client_params); 65 | 66 | /* Methods from RobotControl */ 67 | void command(const Command & command); 68 | float setSpeed(float speed); 69 | float getSpeed(); 70 | void getStatus(Status & status); 71 | 72 | /* Methods from RobotControlAsync */ 73 | dds::rpc::future command_async(const robot::Command & command); 74 | dds::rpc::future setSpeed_async(float speed); 75 | dds::rpc::future getSpeed_async(); 76 | dds::rpc::future getStatus_async(); 77 | 78 | }; 79 | 80 | class Service : public dds::rpc::ServiceEndpoint 81 | { 82 | public: 83 | 84 | Service(); 85 | 86 | template 87 | Service(Impl & impl); 88 | 89 | template 90 | Service(Impl & impl, dds::rpc::Server & server); 91 | 92 | template 93 | Service(Impl & impl, 94 | dds::rpc::Server & server, 95 | const dds::rpc::ServiceParams & service_params); 96 | 97 | }; 98 | 99 | }; 100 | 101 | } // namespace robot 102 | 103 | 104 | #include "RobotControlSupport.hpp" 105 | 106 | #endif // ROBOTCONTROL_SUPPORT_H 107 | -------------------------------------------------------------------------------- /normative/function_call.h: -------------------------------------------------------------------------------- 1 | #ifndef OMG_DDS_RPC_FUNCTION_CALL_H 2 | #define OMG_DDS_RPC_FUNCTION_CALL_H 3 | 4 | #include 5 | #include 6 | 7 | #include "normative/request_reply.h" // standard 8 | 9 | #include "vendor_dependent.h" 10 | 11 | namespace dds { namespace rpc { 12 | 13 | class Server; 14 | enum ServiceStatus { CLOSED, PAUSED, RUNNING }; 15 | 16 | template 17 | struct interface_traits 18 | { 19 | typedef Iface InterfaceType; 20 | typedef typename Iface::ProxyType ProxyType; 21 | typedef typename Iface::RequestType RequestType; 22 | typedef typename Iface::ReplyType ReplyType; 23 | }; 24 | 25 | class Exception : public std::exception 26 | { 27 | std::string message_; 28 | 29 | public: 30 | Exception(); 31 | Exception(const char *msg); 32 | 33 | virtual ~Exception() throw(); 34 | virtual void raise() const = 0; 35 | }; 36 | 37 | class ServiceParams 38 | { 39 | public: 40 | /* DomainParticipant argument is optional. When it's not provided, either lookup 41 | a default DomainParticipant or create one. 42 | */ 43 | ServiceParams(); 44 | ServiceParams(const ServiceParams & other); 45 | ServiceParams & operator = (const ServiceParams & that); 46 | 47 | ServiceParams & service_name(const std::string &service_name); 48 | ServiceParams & instance_name(const std::string &instance_name); 49 | ServiceParams & request_topic_name(const std::string &req_topic); 50 | ServiceParams & reply_topic_name(const std::string &rep_topic); 51 | ServiceParams & datawriter_qos(dds_entity_traits::DataWriterQos qos); 52 | ServiceParams & datareader_qos(dds_entity_traits::DataReaderQos qos); 53 | ServiceParams & publisher(dds_entity_traits::Publisher publisher); 54 | ServiceParams & subscriber(dds_entity_traits::Subscriber subscriber); 55 | ServiceParams & domain_participant(dds_entity_traits::DomainParticipant part); 56 | 57 | std::string service_name() const; 58 | std::string instance_name() const; 59 | std::string request_topic_name() const; 60 | std::string reply_topic_name() const; 61 | dds_entity_traits::DataWriterQos datawriter_qos() const; 62 | dds_entity_traits::DataReaderQos datareader_qos() const; 63 | dds_entity_traits::Publisher publisher() const; 64 | dds_entity_traits::Subscriber subscriber() const; 65 | dds_entity_traits::DomainParticipant domain_participant() const; 66 | 67 | protected: 68 | typedef details::vendor_dependent::type VendorDependent; 69 | VendorDependent impl_; 70 | 71 | public: 72 | VendorDependent get_impl() const; 73 | }; 74 | 75 | class ClientParams 76 | { 77 | public: 78 | /* DomainParticipant argument is optional. When it's not provided, either lookup 79 | a default DomainParticipant or create one. 80 | */ 81 | ClientParams(); 82 | ClientParams(const ClientParams & other); 83 | ClientParams & operator = (const ClientParams & that); 84 | 85 | ClientParams & service_name(const std::string &service_name); 86 | ClientParams & instance_name(const std::string &instance_name); 87 | ClientParams & request_topic_name(const std::string &req_topic); 88 | ClientParams & reply_topic_name(const std::string &rep_topic); 89 | ClientParams & datawriter_qos(const dds_entity_traits::DataWriterQos & qos); 90 | ClientParams & datareader_qos(const dds_entity_traits::DataReaderQos & qos); 91 | ClientParams & publisher(dds_entity_traits::Publisher publisher); 92 | ClientParams & subscriber(dds_entity_traits::Subscriber subscriber); 93 | ClientParams & domain_participant(dds_entity_traits::DomainParticipant part); 94 | 95 | const std::string & service_name() const; 96 | const std::string & instance_name() const; 97 | const std::string & request_topic_name() const; 98 | const std::string & reply_topic_name() const; 99 | const dds_entity_traits::DataWriterQos & datawriter_qos() const; 100 | const dds_entity_traits::DataReaderQos & datareader_qos() const; 101 | dds_entity_traits::Publisher publisher() const; 102 | dds_entity_traits::Subscriber subscriber() const; 103 | dds_entity_traits::DomainParticipant domain_participant() const; 104 | 105 | protected: 106 | typedef details::vendor_dependent::type VendorDependent; 107 | VendorDependent impl_; 108 | 109 | public: 110 | VendorDependent get_impl() const; 111 | }; 112 | 113 | class ServerParams 114 | { 115 | public: 116 | ServerParams(); 117 | ServerParams(const ServerParams & other); 118 | ServerParams & operator = (const ServerParams & that); 119 | 120 | ServerParams & default_service_params(const ServiceParams & service_params); 121 | 122 | ServiceParams default_service_params() const; 123 | 124 | protected: 125 | typedef details::vendor_dependent::type VendorDependent; 126 | VendorDependent impl_; 127 | 128 | public: 129 | VendorDependent get_impl() const; 130 | }; 131 | 132 | class ServiceEndpoint : public RPCEntity 133 | { 134 | protected: 135 | 136 | template 137 | explicit ServiceEndpoint(Impl impl, int disambiguate); 138 | 139 | public: 140 | 141 | typedef details::vendor_dependent::type VendorDependent; 142 | 143 | ServiceEndpoint(); 144 | ServiceEndpoint(const ServiceEndpoint &); 145 | 146 | template 147 | typename dds_type_traits::DataReader get_request_datareader() const; 148 | 149 | template 150 | typename dds_type_traits::DataWriter get_reply_datawriter() const; 151 | 152 | void pause(); 153 | void resume(); 154 | ServiceStatus status() const; 155 | ServiceParams get_service_params() const; 156 | 157 | VendorDependent get_impl() const; 158 | }; 159 | 160 | class ClientEndpoint : public ServiceProxy 161 | { 162 | protected: 163 | 164 | template 165 | explicit ClientEndpoint(Impl impl, int disambiguate); 166 | 167 | public: 168 | 169 | typedef details::vendor_dependent::type VendorDependent; 170 | 171 | ClientEndpoint(); 172 | ClientEndpoint(const ClientEndpoint &); 173 | 174 | template 175 | typename dds_type_traits::DataWriter get_request_datawriter() const; 176 | 177 | template 178 | typename dds_type_traits::DataReader get_reply_datareader() const; 179 | 180 | dds::rpc::ClientParams get_client_params(); 181 | 182 | VendorDependent get_impl() const; 183 | }; 184 | 185 | class Server : public RPCEntity 186 | { 187 | public: 188 | 189 | typedef details::vendor_dependent::type VendorDependent; 190 | 191 | // may reuse an exising participant 192 | Server(); 193 | 194 | explicit Server(const ServerParams & server_params); 195 | 196 | // blocking 197 | void run(); 198 | 199 | // non-blocking 200 | void run(const dds::Duration & max_wait); 201 | 202 | VendorDependent get_impl() const; 203 | }; 204 | 205 | } // namespace rpc 206 | } // namespace dds 207 | 208 | #include "function_call.hpp" 209 | 210 | #endif // OMG_DDS_RPC_FUNCTION_CALL_H 211 | 212 | -------------------------------------------------------------------------------- /normative/request_reply.h: -------------------------------------------------------------------------------- 1 | #ifndef OMG_DDS_RPC_REQUEST_REPLY_H 2 | #define OMG_DDS_RPC_REQUEST_REPLY_H 3 | 4 | #include 5 | 6 | #include "vendor_dependent.h" 7 | #include "normative/sample.h" // standard 8 | 9 | namespace dds { 10 | 11 | namespace rpc { 12 | 13 | class RPCEntity 14 | { 15 | public: 16 | RPCEntity(); 17 | RPCEntity(const RPCEntity &); 18 | 19 | bool operator == (const RPCEntity &); 20 | void close(); 21 | bool is_null() const; 22 | 23 | protected: 24 | 25 | template 26 | explicit RPCEntity(Impl impl, int disambiguate); 27 | 28 | protected: 29 | typedef details::vendor_dependent::type VendorDependent; 30 | VendorDependent impl_; 31 | 32 | public: 33 | VendorDependent get_impl() const; 34 | }; 35 | 36 | class ServiceProxy : public RPCEntity 37 | { 38 | protected: 39 | 40 | template 41 | explicit ServiceProxy(Impl impl, int disambiguate); 42 | 43 | public: 44 | 45 | ServiceProxy(); 46 | ServiceProxy(const ServiceProxy &); 47 | 48 | void bind(const std::string & instance_name); 49 | void unbind(); 50 | bool is_bound() const; 51 | std::string get_bound_instance_name() const; 52 | std::vector get_discoverd_service_instances() const; 53 | 54 | void wait_for_service(); 55 | void wait_for_service(const dds::Duration & maxWait); 56 | 57 | void wait_for_service(std::string instanceName); 58 | void wait_for_service(const dds::Duration & maxWait, 59 | std::string instanceName); 60 | 61 | void wait_for_services(int count); 62 | void wait_for_services(const dds::Duration & maxWait, int count); 63 | 64 | void wait_for_services(const std::vector & instanceNames); 65 | void wait_for_services(const dds::Duration & maxWait, 66 | const std::vector & instanceNames); 67 | 68 | future wait_for_service_async(); 69 | future wait_for_service_async(std::string instanceName); 70 | future wait_for_services_async(int count); 71 | future wait_for_services_async(const std::vector & instanceNames); 72 | }; 73 | 74 | 75 | template 76 | class Requester : public ServiceProxy 77 | { 78 | public: 79 | 80 | typedef TReq RequestType; 81 | 82 | typedef TRep ReplyType; 83 | 84 | typedef typename dds::dds_type_traits::DataWriter RequestDataWriter; 85 | 86 | typedef typename dds::dds_type_traits::DataReader ReplyDataReader; 87 | 88 | typedef typename dds::dds_type_traits::LoanedSamplesType LoanedSamplesType; 89 | 90 | typedef RequesterParams Params; 91 | 92 | typedef typename details::vendor_dependent>::type VendorDependent; 93 | 94 | Requester(); 95 | 96 | explicit Requester(const RequesterParams& params); 97 | 98 | Requester (const Requester &); 99 | 100 | void swap(Requester & other); 101 | 102 | Requester & operator = (const Requester &); 103 | 104 | virtual ~Requester(); 105 | 106 | void send_request(WriteSample &request); 107 | 108 | void send_request(WriteSampleRef & wsref); 109 | 110 | future> send_request_async(const TReq &); 111 | 112 | #ifdef OMG_DDS_RPC_BASIC_PROFILE 113 | void send_request(TReq & request); 114 | void send_request_oneway(TReq &); 115 | #endif 116 | 117 | #ifdef OMG_DDS_RPC_ENHANCED_PROFILE 118 | void send_request(const TReq & request); 119 | void send_request_oneway(const TReq &); 120 | #endif 121 | 122 | bool receive_reply( 123 | Sample& reply, 124 | const dds::Duration & timeout); 125 | 126 | bool receive_reply( 127 | SampleRef reply, 128 | const dds::Duration & timeout); 129 | 130 | bool receive_reply( 131 | Sample& reply, 132 | const dds::SampleIdentity & relatedRequestId, 133 | const dds::Duration & timeout); 134 | 135 | bool receive_reply( 136 | SampleRef reply, 137 | const dds::SampleIdentity & relatedRequestId, 138 | const dds::Duration & timeout); 139 | 140 | LoanedSamples receive_replies(const dds::Duration & max_wait); 141 | 142 | LoanedSamples receive_replies(int min_count, 143 | int max_count, 144 | const dds::Duration & max_wait); 145 | 146 | bool wait_for_replies( 147 | int min_count, 148 | const dds::Duration & max_wait); 149 | 150 | bool wait_for_replies(const dds::Duration & max_wait); 151 | 152 | bool wait_for_replies( 153 | int min_count, 154 | const dds::Duration & max_wait, 155 | const dds::SampleIdentity & related_request_id); 156 | 157 | bool take_reply(Sample& reply); 158 | 159 | bool take_reply(SampleRef reply); 160 | 161 | bool take_reply( 162 | Sample& reply, 163 | const dds::SampleIdentity& related_request_id); 164 | 165 | bool take_reply( 166 | SampleRef reply, 167 | const dds::SampleIdentity& related_request_id); 168 | 169 | LoanedSamples take_replies(int max_count); 170 | 171 | LoanedSamples take_replies( 172 | int max_count, 173 | const dds::SampleIdentity& related_request_id); 174 | 175 | LoanedSamples take_replies( 176 | const dds::SampleIdentity& related_request_id); 177 | 178 | inline bool read_reply(Sample& reply); 179 | 180 | inline bool read_reply(SampleRef reply); 181 | 182 | inline bool read_reply( 183 | Sample& reply, 184 | const dds::SampleIdentity& related_request_id); 185 | 186 | inline bool read_reply( 187 | SampleRef reply, 188 | const dds::SampleIdentity& related_request_id); 189 | 190 | LoanedSamples read_replies(int max_count); 191 | 192 | LoanedSamples read_replies( 193 | int max_count, 194 | const dds::SampleIdentity& related_request_id); 195 | 196 | LoanedSamples read_replies( 197 | const dds::SampleIdentity& related_request_id); 198 | 199 | bool receive_nondata_samples(bool enable); 200 | 201 | RequesterParams get_requester_params() const; 202 | 203 | RequestDataWriter get_request_datawriter() const; 204 | 205 | ReplyDataReader get_reply_datareader() const; 206 | 207 | VendorDependent get_impl(); 208 | }; 209 | 210 | template 211 | class Replier : public RPCEntity 212 | { 213 | public: 214 | 215 | typedef TReq RequestType; 216 | 217 | typedef TRep ReplyType; 218 | 219 | typedef typename dds::dds_type_traits::DataWriter ReplyDataWriter; 220 | 221 | typedef typename dds::dds_type_traits::DataReader RequestDataReader; 222 | 223 | typedef typename dds::dds_type_traits::LoanedSamplesType LoanedSamplesType; 224 | 225 | typedef ReplierParams Params; 226 | 227 | typedef typename details::vendor_dependent>::type VendorDependent; 228 | 229 | Replier(); 230 | 231 | Replier(const Replier &); 232 | 233 | Replier & operator = (const Replier &); 234 | 235 | explicit Replier(const ReplierParams & params); 236 | 237 | virtual ~Replier(); 238 | 239 | void swap(Replier & other); 240 | 241 | void send_reply( 242 | WriteSample & reply, 243 | const dds::SampleIdentity& related_request_id); 244 | 245 | void send_reply( 246 | WriteSampleRef & reply, 247 | const dds::SampleIdentity& related_request_id); 248 | 249 | #ifdef OMG_DDS_RPC_BASIC_PROFILE 250 | void send_reply( 251 | TRep & reply, 252 | const dds::SampleIdentity& related_request_id); 253 | #endif 254 | 255 | #ifdef OMG_DDS_RPC_ENHANCED_PROFILE 256 | void send_reply( 257 | const TRep & reply, 258 | const dds::SampleIdentity& related_request_id); 259 | #endif 260 | 261 | bool receive_request( 262 | Sample & request, 263 | const dds::Duration & max_wait); 264 | 265 | bool receive_request( 266 | SampleRef request, 267 | const dds::Duration & max_wait); 268 | 269 | LoanedSamplesType receive_requests( 270 | const dds::Duration & max_wait); 271 | 272 | LoanedSamplesType receive_requests( 273 | int min_request_count, 274 | int max_request_count, 275 | const dds::Duration& max_wait); 276 | 277 | bool wait_for_requests( 278 | const dds::Duration & max_wait); 279 | 280 | bool wait_for_requests( 281 | int min_count, 282 | const dds::Duration & max_wait); 283 | 284 | bool take_request(Sample & request); 285 | 286 | bool take_request(SampleRef request); 287 | 288 | LoanedSamplesType take_requests(int max_samples); 289 | 290 | bool read_request(Sample & request); 291 | 292 | bool read_request(SampleRef request); 293 | 294 | LoanedSamplesType read_requests(int max_samples); 295 | 296 | const ReplierParams & get_replier_params() const; 297 | 298 | bool receive_nondata_samples(bool enable); 299 | 300 | RequestDataReader get_request_datareader() const; 301 | 302 | ReplyDataWriter get_reply_datawriter() const; 303 | 304 | VendorDependent get_impl() const; 305 | }; 306 | 307 | template 308 | void swap(Replier & cr1, 309 | Replier & cr2) 310 | { 311 | cr1.swap(cr2); 312 | } 313 | 314 | class ListenerBase 315 | { 316 | virtual ~ListenerBase(); 317 | }; 318 | 319 | template 320 | class SimpleReplierListener : public ListenerBase 321 | { 322 | public: 323 | virtual TRep * process_request(const Sample &, 324 | const dds::SampleIdentity &) = 0; 325 | virtual ~SimpleReplierListener(); 326 | }; 327 | 328 | template 329 | class ReplierListener : public ListenerBase 330 | { 331 | public: 332 | virtual void on_request_available(Replier &) = 0; 333 | virtual ~ReplierListener(); 334 | }; 335 | 336 | template 337 | class SimpleRequesterListener : public ListenerBase 338 | { 339 | public: 340 | virtual void process_reply(const Sample &, 341 | const dds::SampleIdentity &) = 0; 342 | virtual ~SimpleRequesterListener(); 343 | }; 344 | 345 | template 346 | class RequesterListener : public ListenerBase 347 | { 348 | public: 349 | virtual void on_reply_available(Requester &) = 0; 350 | virtual ~RequesterListener(); 351 | }; 352 | 353 | class RequesterParams 354 | { 355 | public: 356 | /* Normative: DomainParticipant argument is optional. When it's not provided, either 357 | lookup a default DomainParticipant or create one. 358 | */ 359 | RequesterParams (); 360 | RequesterParams(const RequesterParams & other); 361 | RequesterParams & operator = (const RequesterParams & that); 362 | 363 | template 364 | RequesterParams & simple_requester_listener( 365 | SimpleRequesterListener *listener); 366 | 367 | template 368 | RequesterParams & requester_listener( 369 | RequesterListener *listener); 370 | 371 | RequesterParams & domain_participant(dds_entity_traits::DomainParticipant participant); 372 | RequesterParams & publisher(dds_entity_traits::Publisher publisher); 373 | RequesterParams & subscriber(dds_entity_traits::Subscriber subscriber); 374 | RequesterParams & datawriter_qos(dds_entity_traits::DataWriterQos qos); 375 | RequesterParams & datareader_qos(dds_entity_traits::DataReaderQos qos); 376 | RequesterParams & service_name (const std::string &name); 377 | RequesterParams & request_topic_name (const std::string &name); 378 | RequesterParams & reply_topic_name (const std::string &name); 379 | 380 | dds_entity_traits::DomainParticipant domain_participant() const; 381 | dds_entity_traits::Publisher publisher() const; 382 | dds_entity_traits::Subscriber subscriber() const; 383 | dds_entity_traits::DataWriterQos datawriter_qos() const; 384 | dds_entity_traits::DataReaderQos datareader_qos() const; 385 | ListenerBase * simple_requester_listener() const; 386 | ListenerBase * requester_listener() const; 387 | std::string service_name() const; 388 | std::string request_topic_name() const; 389 | std::string reply_topic_name() const; 390 | 391 | private: 392 | typedef details::vendor_dependent::type VendorDependent; 393 | VendorDependent impl_; 394 | 395 | public: 396 | VendorDependent get_impl(); 397 | }; 398 | 399 | 400 | class ReplierParams 401 | { 402 | public: 403 | /* Normative: DomainParticipant argument is optional. When it's not provided, either 404 | lookup a default DomainParticipant or create one. 405 | */ 406 | ReplierParams (); 407 | ReplierParams(const ReplierParams & other); 408 | ReplierParams & operator = (const ReplierParams & that); 409 | 410 | template 411 | ReplierParams & simple_replier_listener ( 412 | SimpleReplierListener *listener); 413 | 414 | template 415 | ReplierParams & replier_listener ( 416 | ReplierListener *listener); 417 | 418 | ReplierParams & domain_participant(dds_entity_traits::DomainParticipant participant); 419 | ReplierParams & service_name (const std::string &service_name); 420 | ReplierParams & instance_name (const std::string &service_name); 421 | ReplierParams & request_topic_name (const std::string &req_topic); 422 | ReplierParams & reply_topic_name (const std::string &rep_topic); 423 | ReplierParams & datawriter_qos(dds_entity_traits::DataWriterQos qos); 424 | ReplierParams & datareader_qos(dds_entity_traits::DataReaderQos qos); 425 | ReplierParams & publisher(dds_entity_traits::Publisher publisher); 426 | ReplierParams & subscriber(dds_entity_traits::Subscriber subscriber); 427 | 428 | dds_entity_traits::DomainParticipant domain_participant() const; 429 | ListenerBase * simple_replier_listener() const; 430 | ListenerBase * replier_listener() const; 431 | std::string service_name() const; 432 | std::string instance_name() const; 433 | std::string request_topic_name() const; 434 | std::string reply_topic_name() const; 435 | dds_entity_traits::DataWriterQos datawriter_qos() const; 436 | dds_entity_traits::DataReaderQos datareader_qos() const; 437 | dds_entity_traits::Publisher publisher() const; 438 | dds_entity_traits::Subscriber subscriber() const; 439 | 440 | private: 441 | typedef details::vendor_dependent::type VendorDependent; 442 | VendorDependent impl_; 443 | 444 | public: 445 | VendorDependent get_impl(); 446 | }; 447 | 448 | } // namespace rpc 449 | 450 | } // namespace dds 451 | 452 | #include "request_reply.hpp" // vendor dependent 453 | 454 | #endif // OMG_DDS_RPC_REQUEST_REPLY_H 455 | 456 | -------------------------------------------------------------------------------- /normative/sample.h: -------------------------------------------------------------------------------- 1 | #ifndef OMG_DDS_RPC_INFRASTRUCTURE_H 2 | #define OMG_DDS_RPC_INFRASTRUCTURE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef OMG_DDS_RPC_REFERENCE_IMPLEMENTATION 10 | 11 | #include "vendor_dependent.h" 12 | 13 | #else 14 | 15 | namespace dds { 16 | 17 | namespace details { 18 | 19 | template 20 | struct if_ { 21 | typedef T type; 22 | }; 23 | 24 | template 25 | struct if_ { 26 | typedef U type; 27 | }; 28 | 29 | } // namespace details 30 | 31 | template class SampleIterator; 32 | template class Sample; 33 | template class SampleRef; 34 | template class WriteSample; 35 | template class WriteSampleRef; 36 | template class LoanedSamples; 37 | template class SharedSamples; 38 | 39 | class SampleInfo; 40 | class SampleInfoSeq; 41 | class SampleIdentity; 42 | 43 | template 44 | struct dds_type_traits 45 | { 46 | typedef typename T::Seq Seq; 47 | typedef const typename T::Seq ConstSeq; 48 | typedef typename T::DataReader DataReader; 49 | typedef typename T::DataWriter DataWriter; 50 | 51 | typedef dds::SampleRef SampleRefType; 52 | typedef dds::SampleRef SampleIteratorValueType; 53 | typedef dds::SampleRef ConstSampleIteratorValueType; 54 | typedef dds::LoanedSamples LoanedSamplesType; 55 | typedef dds::SharedSamples SharedSamplesType; 56 | typedef dds::SampleIterator iterator; 57 | typedef dds::SampleIterator const_iterator; 58 | }; 59 | 60 | template <> 61 | struct dds_type_traits 62 | { 63 | typedef dds::SampleInfoSeq Seq; 64 | typedef const dds::SampleInfoSeq ConstSeq; 65 | }; 66 | 67 | struct dds_entity_traits; // defined in vendor_dependent.h 68 | 69 | template 70 | class Sample 71 | { 72 | public: 73 | typedef T Data; 74 | typedef T& DataReference; 75 | typedef const T& ConstDataReference; 76 | typedef typename dds::dds_type_traits::Seq Seq; 77 | typedef typename dds::dds_type_traits::DataReader DataReader; 78 | typedef typename dds::dds_type_traits::DataWriter DataWriter; 79 | 80 | Sample(); 81 | 82 | Sample(const Sample& other); 83 | 84 | Sample(SampleRef sample_ref); 85 | 86 | Sample(const T &data, const dds::SampleInfo& info); 87 | 88 | Sample & operator = (SampleRef sample_ref); 89 | 90 | dds::SampleIdentity identity() const; 91 | 92 | dds::SampleIdentity related_identity() const; 93 | 94 | void swap(Sample & other); 95 | 96 | T& data(); 97 | 98 | dds::SampleInfo& info(); 99 | 100 | const T& data() const; 101 | 102 | const dds::SampleInfo& info() const; 103 | 104 | operator DataReference (); 105 | 106 | operator ConstDataReference () const; 107 | 108 | void set_data(const T &t); 109 | 110 | void set_data(const T *t); 111 | 112 | void set_info(const dds::SampleInfo &i); 113 | 114 | void set_info(const dds::SampleInfo *i); 115 | }; 116 | 117 | template 118 | class SampleRef 119 | { 120 | public: 121 | typedef T Data; 122 | typedef T& DataReference; 123 | typedef const T& ConstDataReference; 124 | typedef typename dds::dds_type_traits::Seq Seq; 125 | typedef typename dds::dds_type_traits::DataReader DataReader; 126 | typedef typename dds::dds_type_traits::DataWriter DataWriter; 127 | 128 | public: 129 | SampleRef(); 130 | 131 | SampleRef(T * data, dds::SampleInfo * info); 132 | 133 | SampleRef(T & data, dds::SampleInfo & info); 134 | 135 | SampleRef(Sample & sample); 136 | 137 | SampleRef & operator = (Sample & sample); 138 | 139 | T & data() const; 140 | 141 | dds::SampleInfo & info() const; 142 | 143 | operator T & () const; 144 | 145 | SampleRef * operator ->(); 146 | 147 | const SampleRef * operator ->() const; 148 | 149 | void set_data(T * data); 150 | 151 | void set_data(T & data); 152 | 153 | void set_info(dds::SampleInfo * info); 154 | 155 | void set_info(dds::SampleInfo & info); 156 | 157 | bool is_nil_data() const; 158 | 159 | bool is_nil_info() const; 160 | 161 | void swap(SampleRef & other) throw(); 162 | 163 | dds::SampleIdentity identity() const; 164 | 165 | dds::SampleIdentity related_identity() const; 166 | }; 167 | 168 | template 169 | class SampleIterator 170 | { 171 | public: 172 | typedef std::random_access_iterator_tag iterator_category; 173 | 174 | typedef typename details::if_< 175 | IsConst, 176 | typename dds_type_traits::ConstSampleIteratorValueType, 177 | typename dds_type_traits::SampleIteratorValueType>::type 178 | value_type; 179 | 180 | typedef value_type reference; 181 | typedef value_type pointer; 182 | typedef std::ptrdiff_t difference_type; 183 | 184 | typedef typename details::if_< 185 | IsConst, 186 | typename dds_type_traits::ConstSeq, 187 | typename dds_type_traits::Seq>::type Seq; 188 | 189 | typedef typename details::if_< 190 | IsConst, 191 | typename dds_type_traits::ConstSeq, 192 | typename dds_type_traits::Seq>::type InfoSeq; 193 | 194 | SampleIterator(); 195 | 196 | explicit SampleIterator(Seq & seq, 197 | InfoSeq & info_seq, 198 | int position = 0); 199 | 200 | SampleIterator (const SampleIterator & si); 201 | 202 | SampleIterator & operator = (const SampleIterator & si); 203 | 204 | value_type operator * () const; 205 | 206 | value_type operator ->() const; 207 | 208 | value_type operator [] (difference_type offset) const; 209 | 210 | SampleIterator & operator ++ (); 211 | 212 | SampleIterator operator ++ (int); 213 | 214 | SampleIterator & operator -- (); 215 | 216 | SampleIterator operator -- (int); 217 | 218 | SampleIterator & operator -= (difference_type i); 219 | 220 | SampleIterator & operator += (difference_type i); 221 | 222 | SampleIterator operator - (difference_type i) const; 223 | 224 | SampleIterator operator + (difference_type i) const; 225 | 226 | difference_type operator - (const SampleIterator & s2) const; 227 | 228 | bool operator < (const SampleIterator & s2) const; 229 | 230 | bool operator > (const SampleIterator & s2) const; 231 | 232 | bool operator <= (const SampleIterator & s2) const; 233 | 234 | bool operator >= (const SampleIterator & s2) const; 235 | 236 | bool operator == (const SampleIterator & s2) const; 237 | 238 | bool operator != (const SampleIterator & s2) const; 239 | 240 | bool is_end() const; 241 | }; 242 | 243 | template 244 | LoanedSamples move(LoanedSamples & ls) throw(); 245 | 246 | // This class implements the move-constructor idiom as in DDS-PSM-Cxx 247 | template 248 | class LoanedSamples 249 | { 250 | public: 251 | typedef typename dds_type_traits::Seq Seq; 252 | typedef typename dds_type_traits::DataReader DataReader; 253 | 254 | typedef SampleIterator iterator; 255 | typedef SampleIterator const_iterator; 256 | 257 | typedef typename dds_type_traits::SampleIteratorValueType value_type; 258 | typedef typename dds_type_traits::ConstSampleIteratorValueType const_value_type; 259 | typedef std::ptrdiff_t difference_type; 260 | 261 | private: 262 | struct LoanMemento 263 | { 264 | void * data; 265 | }; 266 | 267 | public: 268 | 269 | LoanedSamples(); 270 | 271 | static LoanedSamples move_construct_from_loans( 272 | DataReader reader, 273 | Seq & data_seq, 274 | dds::SampleInfoSeq & info_seq); 275 | 276 | void release( 277 | DataReader & reader_ptr, 278 | Seq & data_seq, 279 | dds::SampleInfoSeq & info_seq); 280 | 281 | #ifdef OMG_DDS_RPC_HASCPP11 282 | 283 | LoanedSamples(const LoanedSamples &) = delete; 284 | LoanedSamples & operator = (const LoanedSamples &) = delete; 285 | 286 | LoanedSamples(LoanedSamples &&) noexcept; 287 | LoanedSamples & operator = (LoanedSamples &&) noexcept; 288 | 289 | #else 290 | LoanedSamples(LoanMemento loan_memento) throw(); 291 | 292 | LoanedSamples & operator = (LoanMemento loan_memento) throw(); 293 | 294 | operator LoanMemento () throw(); 295 | 296 | friend LoanedSamples move<> (LoanedSamples &) throw(); 297 | #endif 298 | 299 | ~LoanedSamples() throw(); 300 | 301 | Seq & data_seq(); 302 | 303 | dds::SampleInfoSeq & info_seq(); 304 | 305 | const Seq & data_seq() const; 306 | 307 | const dds::SampleInfoSeq & info_seq() const; 308 | 309 | value_type operator [] (size_t index); 310 | 311 | const_value_type operator [] (size_t index) const; 312 | 313 | int length() const; 314 | 315 | void return_loan(); 316 | 317 | void swap(LoanedSamples & that) throw(); 318 | 319 | SharedSamples to_shared() throw(); 320 | 321 | iterator begin(); 322 | 323 | iterator end(); 324 | 325 | const_iterator begin() const; 326 | 327 | const_iterator end() const; 328 | }; 329 | 330 | template 331 | class SharedSamples 332 | { 333 | public: 334 | typedef typename dds_type_traits::Seq Seq; 335 | typedef typename dds_type_traits::DataReader DataReader; 336 | 337 | typedef SampleIterator iterator; 338 | typedef SampleIterator const_iterator; 339 | 340 | typedef typename dds_type_traits::SampleIteratorValueType value_type; 341 | typedef typename dds_type_traits::ConstSampleIteratorValueType const_value_type; 342 | typedef std::ptrdiff_t difference_type; 343 | 344 | public: 345 | 346 | SharedSamples(); 347 | 348 | SharedSamples(const SharedSamples &); 349 | 350 | SharedSamples & operator = (const SharedSamples &); 351 | 352 | ~SharedSamples() throw(); 353 | 354 | Seq & data_seq(); 355 | 356 | dds::SampleInfoSeq & info_seq(); 357 | 358 | const Seq & data_seq() const; 359 | 360 | const dds::SampleInfoSeq & info_seq() const; 361 | 362 | value_type operator [] (size_t index); 363 | 364 | const_value_type operator [] (size_t index) const; 365 | 366 | int length() const; 367 | 368 | void swap(SharedSamples & that) throw(); 369 | 370 | iterator begin(); 371 | 372 | iterator end(); 373 | 374 | const_iterator begin() const; 375 | 376 | const_iterator end() const; 377 | }; 378 | 379 | template 380 | class WriteSample 381 | { 382 | public: 383 | 384 | WriteSample(); 385 | 386 | WriteSample(const WriteSample& other); 387 | 388 | WriteSample(const T & data); 389 | 390 | WriteSample(const WriteSampleRef & wsref); 391 | 392 | WriteSample & operator = (const WriteSampleRef & wsref); 393 | 394 | WriteSample & operator = (const WriteSample & ws); 395 | 396 | const T & data() const; 397 | 398 | T & data(); 399 | 400 | void set_data(const T & data); 401 | 402 | void set_identity(const dds::SampleIdentity & id); 403 | 404 | void swap(WriteSample & other) throw(); 405 | 406 | dds::SampleIdentity identity() const; 407 | }; 408 | 409 | template 410 | class WriteSampleRef 411 | { 412 | public: 413 | 414 | WriteSampleRef(); 415 | 416 | WriteSampleRef(const T & data); 417 | 418 | WriteSampleRef(WriteSample & ws); 419 | 420 | WriteSampleRef(const WriteSampleRef & wsref); 421 | 422 | WriteSampleRef & operator = (WriteSample & ws); 423 | 424 | WriteSampleRef & operator = (const WriteSampleRef & wsref); 425 | 426 | const T & data() const; 427 | 428 | T & data(); 429 | 430 | void set_data(const T & data); 431 | 432 | void set_identity(const dds::SampleIdentity & id); 433 | 434 | void swap(WriteSampleRef & other) throw(); 435 | 436 | dds::SampleIdentity identity() const; 437 | }; 438 | 439 | 440 | #ifdef OMG_DDS_RPC_HASCPP11 441 | 442 | template 443 | LoanedSamples move(LoanedSamples & ls) noexcept 444 | { 445 | return std::move(ls); 446 | } 447 | 448 | #else 449 | template 450 | LoanedSamples move(LoanedSamples & ls) throw() 451 | { 452 | return LoanedSamples(typename LoanedSamples::LoanMemento(ls)); 453 | } 454 | #endif // OMG_DDS_RPC_HASCPP11 455 | 456 | template 457 | typename LoanedSamples::iterator begin(LoanedSamples & ls) 458 | { 459 | return ls.begin(); 460 | } 461 | 462 | template 463 | typename LoanedSamples::const_iterator begin(const LoanedSamples & ls) 464 | { 465 | return ls.begin(); 466 | } 467 | 468 | template 469 | typename LoanedSamples::iterator end(LoanedSamples & ls) 470 | { 471 | return ls.end(); 472 | } 473 | 474 | template 475 | typename LoanedSamples::const_iterator end(const LoanedSamples & ls) 476 | { 477 | return ls.end(); 478 | } 479 | 480 | template 481 | void swap(LoanedSamples &ls1, LoanedSamples &ls2) throw() 482 | { 483 | ls1.swap(ls2); 484 | } 485 | 486 | template 487 | typename SharedSamples::iterator begin(SharedSamples & ss) 488 | { 489 | return ss.begin(); 490 | } 491 | 492 | template 493 | typename SharedSamples::const_iterator begin(const SharedSamples & ss) 494 | { 495 | return ss.begin(); 496 | } 497 | 498 | template 499 | typename SharedSamples::iterator end(SharedSamples & ss) 500 | { 501 | return ss.end(); 502 | } 503 | 504 | template 505 | typename SharedSamples::const_iterator end(const SharedSamples & ss) 506 | { 507 | return ss.end(); 508 | } 509 | 510 | template 511 | void swap(SharedSamples &ss1, SharedSamples &ss2) throw() 512 | { 513 | ss1.swap(ss2); 514 | } 515 | 516 | } // namespace dds 517 | 518 | #endif // OMG_DDS_RPC_REFERENCE_IMPLEMENTATION 519 | 520 | 521 | #endif // OMG_DDS_RPC_INFRASTRUCTURE_H 522 | 523 | -------------------------------------------------------------------------------- /request_reply.cxx: -------------------------------------------------------------------------------- 1 | #ifdef USE_RTI_CONNEXT 2 | 3 | #include "normative/request_reply.h" 4 | 5 | //#include "boost/make_shared.hpp" 6 | 7 | //#include 8 | 9 | //#ifdef RTI_WIN32 10 | //#define strcpy(dest, src) strcpy_s(dest, 255, src); 11 | //#endif 12 | 13 | namespace dds { namespace rpc { 14 | 15 | RPCEntity::RPCEntity() 16 | {} 17 | 18 | RPCEntity::RPCEntity(const RPCEntity & entity) 19 | : impl_(entity.impl_) 20 | {} 21 | 22 | bool RPCEntity::operator == (const RPCEntity & entity) 23 | { 24 | return impl_.get() == entity.impl_.get(); 25 | } 26 | 27 | void RPCEntity::close() 28 | { 29 | impl_->close(); 30 | } 31 | 32 | bool RPCEntity::is_null() const 33 | { 34 | return (impl_.get() == 0); 35 | } 36 | 37 | ServiceProxy::ServiceProxy(const ServiceProxy & proxy) 38 | : RPCEntity(proxy) 39 | {} 40 | 41 | void ServiceProxy::bind(const std::string & instance_name) 42 | { 43 | return static_cast(impl_.get())->bind(instance_name); 44 | } 45 | 46 | void ServiceProxy::unbind() 47 | { 48 | return static_cast(impl_.get())->unbind(); 49 | } 50 | 51 | bool ServiceProxy::is_bound() const 52 | { 53 | return static_cast(impl_.get())->is_bound(); 54 | } 55 | 56 | std::string ServiceProxy::get_bound_instance_name() const 57 | { 58 | return static_cast(impl_.get())->get_bound_instance_name(); 59 | } 60 | 61 | std::vector ServiceProxy::get_discoverd_service_instances() const 62 | { 63 | return static_cast(impl_.get())->get_discovered_service_instances(); 64 | } 65 | 66 | RequesterParams::RequesterParams() 67 | : impl_(boost::make_shared()) 68 | { } 69 | 70 | RequesterParams::RequesterParams(const RequesterParams & other) 71 | : impl_(boost::make_shared(*other.impl_.get())) 72 | {} 73 | 74 | RequesterParams & RequesterParams::operator = (const RequesterParams & that) 75 | { 76 | impl_ = boost::make_shared(*that.impl_.get()); 77 | return *this; 78 | } 79 | 80 | RequesterParams & RequesterParams::domain_participant(DDSDomainParticipant * part) 81 | { 82 | impl_->domain_participant(part); 83 | return *this; 84 | } 85 | 86 | RequesterParams & RequesterParams::service_name(const std::string & service_name) 87 | { 88 | impl_->service_name(service_name); 89 | return *this; 90 | } 91 | 92 | DDSDomainParticipant * RequesterParams::domain_participant() const 93 | { 94 | return impl_->domain_participant(); 95 | } 96 | 97 | std::string RequesterParams::service_name() const 98 | { 99 | return impl_->service_name(); 100 | } 101 | 102 | ReplierParams::ReplierParams() 103 | : impl_(boost::make_shared()) 104 | { } 105 | 106 | ReplierParams::ReplierParams(const ReplierParams & other) 107 | : impl_(boost::make_shared(*other.impl_.get())) 108 | {} 109 | 110 | ReplierParams & ReplierParams::operator = (const ReplierParams & that) 111 | { 112 | impl_ = boost::make_shared(*that.impl_.get()); 113 | return *this; 114 | } 115 | 116 | ReplierParams & ReplierParams::domain_participant(DDSDomainParticipant * part) 117 | { 118 | impl_->domain_participant(part); 119 | return *this; 120 | } 121 | 122 | ReplierParams & ReplierParams::service_name(const std::string & service_name) 123 | { 124 | impl_->service_name(service_name); 125 | return *this; 126 | } 127 | 128 | DDSDomainParticipant * ReplierParams::domain_participant() const 129 | { 130 | return impl_->domain_participant(); 131 | } 132 | 133 | std::string ReplierParams::service_name() const 134 | { 135 | return impl_->service_name(); 136 | } 137 | 138 | 139 | namespace details { 140 | 141 | RequesterParamsImpl::RequesterParamsImpl() 142 | : participant_(0) 143 | { } 144 | 145 | void RequesterParamsImpl::domain_participant(DDSDomainParticipant *participant) 146 | { 147 | participant_ = participant; 148 | } 149 | 150 | void RequesterParamsImpl::service_name(const std::string & service_name) 151 | { 152 | service_name_ = service_name; 153 | } 154 | 155 | DDSDomainParticipant * RequesterParamsImpl::domain_participant() const 156 | { 157 | return participant_; 158 | } 159 | 160 | std::string RequesterParamsImpl::service_name() const 161 | { 162 | return service_name_; 163 | } 164 | 165 | ReplierParamsImpl::ReplierParamsImpl() 166 | : participant_(0) 167 | { } 168 | 169 | void ReplierParamsImpl::domain_participant(DDSDomainParticipant *participant) 170 | { 171 | participant_ = participant; 172 | } 173 | 174 | void ReplierParamsImpl::service_name(const std::string & service_name) 175 | { 176 | service_name_ = service_name; 177 | } 178 | 179 | DDSDomainParticipant * ReplierParamsImpl::domain_participant() const 180 | { 181 | return participant_; 182 | } 183 | 184 | std::string ReplierParamsImpl::service_name() const 185 | { 186 | return service_name_; 187 | } 188 | 189 | connext::RequesterParams 190 | to_connext_requester_params(const dds::rpc::RequesterParams & params) 191 | { 192 | DDSDomainParticipant * part = params.domain_participant(); 193 | if(!part) 194 | part = dds::rpc::details::DefaultDomainParticipant::singleton().get(); 195 | 196 | return connext::RequesterParams(part) 197 | .service_name(params.service_name()); 198 | } 199 | 200 | ServiceProxyImpl::~ServiceProxyImpl() 201 | { } 202 | 203 | RPCEntityImpl::~RPCEntityImpl() 204 | { } 205 | 206 | } // namespace details 207 | } // namespace rpc 208 | } //namespace dds 209 | 210 | #endif // USE_RTI_CONNEXT 211 | -------------------------------------------------------------------------------- /request_reply.hpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_RTI_CONNEXT 2 | 3 | #include "connext_cpp/connext_cpp_requester.h" 4 | #include "connext_cpp/connext_cpp_replier.h" 5 | #include "boost/make_shared.hpp" 6 | 7 | #include 8 | 9 | #include "common.h" 10 | 11 | #ifdef RTI_WIN32 12 | #define strcpy(dest, src) strcpy_s(dest, 255, src); 13 | #endif 14 | 15 | namespace dds { 16 | namespace rpc { 17 | namespace details { 18 | 19 | class RPCEntityImpl 20 | { 21 | public: 22 | virtual void close() = 0; 23 | 24 | virtual ~RPCEntityImpl(); 25 | }; 26 | 27 | class ServiceProxyImpl : public RPCEntityImpl 28 | { 29 | public: 30 | 31 | virtual void bind(const std::string & instance_name) = 0; 32 | virtual void unbind() = 0; 33 | virtual bool is_bound() const = 0; 34 | virtual std::string get_bound_instance_name() const = 0; 35 | virtual std::vector get_discovered_service_instances() const = 0; 36 | 37 | virtual void wait_for_service() = 0; 38 | virtual void wait_for_service(const dds::Duration & maxWait) = 0; 39 | 40 | virtual void wait_for_service(std::string instanceName) = 0; 41 | virtual void wait_for_service(const dds::Duration & maxWait, 42 | std::string instanceName) = 0; 43 | 44 | virtual void wait_for_services(int count) = 0; 45 | virtual void wait_for_services(const dds::Duration & maxWait, int count) = 0; 46 | 47 | virtual void wait_for_services(const std::vector & instanceNames) = 0; 48 | virtual void wait_for_services(const dds::Duration & maxWait, 49 | const std::vector & instanceNames) = 0; 50 | 51 | virtual future wait_for_service_async() = 0; 52 | virtual future wait_for_service_async(std::string instanceName) = 0; 53 | virtual future wait_for_services_async(int count) = 0; 54 | virtual future wait_for_services_async( 55 | const std::vector & instanceNames) = 0; 56 | 57 | virtual ~ServiceProxyImpl(); 58 | }; 59 | 60 | connext::RequesterParams 61 | to_connext_requester_params( 62 | const dds::rpc::RequesterParams & params); 63 | 64 | template 65 | class RequesterImpl : public details::ServiceProxyImpl, 66 | public connext::Requester 67 | { 68 | private: 69 | std::string service_name_; 70 | std::string instance_name_; 71 | long sn; 72 | bool suppress_invalid; 73 | std::map>> dict; 74 | std::map id2id_map; 75 | 76 | typedef connext::Requester super; 77 | 78 | struct SyncProxy 79 | { 80 | RequesterImpl * impl; 81 | DDS::SampleIdentity_t identity; 82 | 83 | SyncProxy( 84 | RequesterImpl * i, 85 | const DDS::SampleIdentity_t & sid) 86 | : impl(i), 87 | identity(sid) 88 | { } 89 | }; 90 | 91 | public: 92 | /* 93 | RequesterImpl() 94 | : connext::Requester( 95 | details::to_connext_requester_params(dds::rpc::RequesterParams())), 96 | sn(0), 97 | suppress_invalid(true) 98 | {} 99 | 100 | RequesterImpl( 101 | DDSDomainParticipant * participant, 102 | const std::string& service_name) 103 | : super(participant, service_name), 104 | service_name_(service_name), 105 | sn(0), 106 | suppress_invalid(true) 107 | {} 108 | */ 109 | RequesterImpl( 110 | const dds::rpc::RequesterParams & params) 111 | : service_name_(params.service_name()), 112 | connext::Requester( 113 | details::to_connext_requester_params(params)), 114 | sn(0), 115 | suppress_invalid(true) 116 | { } 117 | 118 | void bind(const std::string & instance_name) override 119 | { } 120 | 121 | void unbind() override 122 | { } 123 | 124 | bool is_bound() const override 125 | { 126 | return false; 127 | } 128 | 129 | std::string get_bound_instance_name() const override 130 | { 131 | return "Unknown"; 132 | } 133 | 134 | std::vector get_discovered_service_instances() const override 135 | { 136 | return std::vector(); 137 | } 138 | 139 | void wait_for_service() override 140 | { } 141 | 142 | void wait_for_service(const dds::Duration & maxWait) override 143 | { } 144 | 145 | void wait_for_service(std::string instanceName) override 146 | { } 147 | 148 | void wait_for_service(const dds::Duration & maxWait, 149 | std::string instanceName) override 150 | { } 151 | 152 | void wait_for_services(int count) override 153 | { } 154 | 155 | void wait_for_services(const dds::Duration & maxWait, int count) override 156 | { } 157 | 158 | void wait_for_services(const std::vector & instanceNames) override 159 | { } 160 | 161 | void wait_for_services(const dds::Duration & maxWait, 162 | const std::vector & instanceNames) override 163 | { } 164 | 165 | future wait_for_service_async() override 166 | { 167 | return future(); 168 | } 169 | 170 | future wait_for_service_async(std::string instanceName) override 171 | { 172 | return future(); 173 | } 174 | 175 | future wait_for_services_async(int count) override 176 | { 177 | return future(); 178 | } 179 | 180 | future wait_for_services_async( 181 | const std::vector & instanceNames) override 182 | { 183 | return future(); 184 | } 185 | 186 | void close() override 187 | { } 188 | 189 | void send_request(WriteSampleRef & wsref) 190 | { 191 | super::send_request(wsref); 192 | } 193 | 194 | bool receive_nondata_samples(bool enable) 195 | { 196 | bool old = suppress_invalid; 197 | suppress_invalid = enable; 198 | return old; 199 | } 200 | 201 | 202 | void send_request(TReq & req) 203 | { 204 | DDS::WriteParams_t wparams; 205 | WriteSampleRef wsref(req, wparams); 206 | //strcpy(req.header.serviceName, service_name_.c_str()); 207 | 208 | if(instance_name_.size() > 0) 209 | strcpy(req.header.instanceName, instance_name_.c_str()); 210 | 211 | req.header.requestId.sequence_number.low = ++sn; 212 | 213 | super::send_request(wsref); 214 | id2id_map[req.header.requestId] = wsref.identity(); 215 | } 216 | 217 | bool receive_reply( 218 | Sample& reply, 219 | const dds::SampleIdentity & relatedRequestId, 220 | const dds::Duration & timeout) 221 | { 222 | if (id2id_map.find(relatedRequestId) != id2id_map.end()) 223 | { 224 | if (super::wait_for_replies(1, timeout)) 225 | { 226 | bool ret = super::take_reply(reply, id2id_map[relatedRequestId]); 227 | if (suppress_invalid && !reply.info().valid_data) 228 | return false; 229 | 230 | id2id_map.erase(relatedRequestId); 231 | return ret; 232 | } 233 | return false; 234 | } 235 | else 236 | { 237 | printf("Unknown dds::SampleIdentity\n"); 238 | return false; 239 | } 240 | } 241 | 242 | static void * execute(void * arg) 243 | { 244 | printf("execute: Created thread = %lld\n", RTIOsapiThread_getCurrentThreadID()); 245 | 246 | std::unique_ptr sync(static_cast(arg)); 247 | 248 | if (sync->impl->wait_for_replies( 249 | 1, dds::Duration::from_seconds(60), sync->identity)) 250 | { 251 | try { 252 | Sample reply; 253 | 254 | if (sync->impl->take_reply(reply, sync->identity)) 255 | { 256 | //if ((reply.data().header.relatedRequestId.sequence_number.low % 10) == 0) 257 | // throw std::runtime_error("% 10 exception!"); 258 | 259 | sync->impl->dict[sync->identity].set_value(reply); 260 | } 261 | else 262 | { 263 | sync->impl->dict[sync->identity]. 264 | set_exception( 265 | std::make_exception_ptr( 266 | std::runtime_error("RequesterImpl::execute: Reply unavailable!"))); 267 | } 268 | } 269 | catch (...) { 270 | sync->impl->dict[sync->identity].set_exception(std::current_exception()); 271 | } 272 | sync->impl->dict.erase(sync->identity); 273 | } 274 | else 275 | printf("Request timed out\n"); 276 | 277 | //printf("Future set. Thread complete\n"); 278 | return NULL; 279 | } 280 | 281 | dds::rpc::future> send_request_async(const TReq &req) 282 | { 283 | struct RTIOsapiThread* tid = 0; 284 | promise> p; 285 | dds::rpc::future> future = p.get_future(); 286 | DDS::WriteParams_t wparams; 287 | WriteSampleRef wsref(const_cast(req), wparams); 288 | 289 | //strcpy(req.header.serviceName, service_name_.c_str()); 290 | 291 | if (instance_name_.size() > 0) 292 | strcpy(req.header.instanceName, instance_name_.c_str()); 293 | 294 | const_cast(req).header.requestId.sequence_number.low = ++sn; 295 | 296 | super::send_request(wsref); 297 | SyncProxy * sync = new SyncProxy(this, wsref.identity()); 298 | dict[wsref.identity()] = std::move(p); 299 | 300 | tid = RTIOsapiThread_new( 301 | "Reply Processor Thread", 302 | RTI_OSAPI_THREAD_PRIORITY_NORMAL, 303 | RTI_OSAPI_THREAD_OPTION_DEFAULT, 304 | 8192, // stack size 305 | NULL, // cpu bitmap 306 | execute, 307 | sync); 308 | 309 | RTIOsapiThread_delete(tid); 310 | return future; 311 | } 312 | }; 313 | 314 | template 315 | connext::ReplierParams 316 | to_connext_replier_params(const rpc::ReplierParams & replier_params) 317 | { 318 | DDSDomainParticipant * part = replier_params.domain_participant(); 319 | if (!part) 320 | part = dds::rpc::details::DefaultDomainParticipant::singleton().get(); 321 | 322 | return connext::ReplierParams(part) 323 | .service_name(replier_params.service_name()); 324 | } 325 | 326 | 327 | template 328 | class ReplierImpl : public connext::Replier, 329 | public RPCEntityImpl 330 | { 331 | private: 332 | std::string service_name_; 333 | std::string instance_name_; 334 | bool suppress_invalid; 335 | 336 | typedef connext::Replier super; 337 | 338 | public: 339 | /* ReplierImpl( 340 | DDSDomainParticipant * participant, 341 | const std::string& service_name) 342 | : connext::Replier(participant, service_name), 343 | service_name_(service_name), 344 | suppress_invalid(true) 345 | {} 346 | */ 347 | ReplierImpl( 348 | const ReplierParams & params) 349 | : connext::Replier(to_connext_replier_params(params)), 350 | suppress_invalid(true) 351 | { 352 | service_name_ = params.service_name(); 353 | } 354 | 355 | /* 356 | void send_reply_connext( 357 | TRep & reply, 358 | const Sample & related_request_sample) 359 | { 360 | reply.header.relatedRequestId = 361 | related_request_sample.data().header.requestId; 362 | super::send_reply(reply, related_request_sample.identity()); 363 | } 364 | */ 365 | 366 | void send_reply( 367 | TRep & reply, 368 | const dds::SampleIdentity & identity) 369 | { 370 | DDS::SampleIdentity_t connext_identity; 371 | memcpy(&connext_identity, &identity, sizeof(DDS::SampleIdentity_t)); 372 | reply.header.relatedRequestId = identity; 373 | reply.header.remoteEx = REMOTE_EX_OK; 374 | super::send_reply(reply, connext_identity); 375 | } 376 | 377 | bool receive_request(Sample & sample, const dds::Duration & timeout) 378 | { 379 | bool ret = super::receive_request(sample, timeout); 380 | if (suppress_invalid && !sample.info().valid_data) 381 | return false; 382 | 383 | return ret; 384 | } 385 | 386 | bool receive_nondata_samples(bool enable) 387 | { 388 | bool old = suppress_invalid; 389 | suppress_invalid = enable; 390 | return old; 391 | } 392 | 393 | void close() 394 | { } 395 | }; 396 | 397 | /****************************************************/ 398 | /************** RequesterParamsImpl *****************/ 399 | /****************************************************/ 400 | 401 | class RequesterParamsImpl 402 | { 403 | DDSDomainParticipant * participant_; 404 | std::string service_name_; 405 | 406 | public: 407 | RequesterParamsImpl(); 408 | 409 | void domain_participant(DDSDomainParticipant *participant); 410 | void service_name(const std::string & service_name); 411 | 412 | DDSDomainParticipant * domain_participant() const; 413 | std::string service_name() const; 414 | 415 | }; 416 | 417 | /****************************************************/ 418 | /************** ReplierParamsImpl *****************/ 419 | /****************************************************/ 420 | 421 | class ReplierParamsImpl 422 | { 423 | DDSDomainParticipant * participant_; 424 | std::string service_name_; 425 | 426 | public: 427 | ReplierParamsImpl(); 428 | 429 | void domain_participant(DDSDomainParticipant *participant); 430 | void service_name(const std::string & service_name); 431 | 432 | DDSDomainParticipant * domain_participant() const; 433 | std::string service_name() const; 434 | 435 | }; 436 | 437 | } // namespace details 438 | 439 | template 440 | RPCEntity::RPCEntity(Impl impl, int) 441 | : impl_(impl) 442 | {} 443 | 444 | template 445 | ServiceProxy::ServiceProxy(Impl impl, int) 446 | : RPCEntity(impl, 0) 447 | {} 448 | 449 | /****************************************************/ 450 | /************** Requester ***************************/ 451 | /****************************************************/ 452 | 453 | 454 | template 455 | Requester::Requester() 456 | : ServiceProxy(new rpc::details::RequesterImpl()) 457 | { } 458 | 459 | template 460 | Requester::Requester(const RequesterParams& params) 461 | : ServiceProxy(new rpc::details::RequesterImpl(params), 0) 462 | { } 463 | 464 | template 465 | Requester::Requester(const Requester & requester) 466 | : ServiceProxy(requester) 467 | { } 468 | 469 | template 470 | void Requester::send_request(TReq & req) 471 | { 472 | auto impl = dynamic_cast *>(impl_.get()); 473 | impl->send_request(req); 474 | } 475 | 476 | template 477 | bool Requester::receive_reply(Sample & sample, const dds::Duration & timeout) 478 | { 479 | auto impl = static_cast *>(impl_.get()); 480 | return impl->receive_reply(sample, timeout); 481 | } 482 | 483 | template 484 | future> Requester::send_request_async(const TReq & req) 485 | { 486 | auto impl = static_cast *>(impl_.get()); 487 | return impl->send_request_async(req); 488 | } 489 | 490 | template 491 | bool Requester::wait_for_replies(const dds::Duration & max_wait) 492 | { 493 | auto impl = static_cast *>(impl_.get()); 494 | return impl->wait_for_replies(max_wait); 495 | } 496 | 497 | #ifdef OMG_DDS_RPC_ENHANCED_PROFILE 498 | 499 | template 500 | void Requester::send_request(WriteSampleRef & wsref) 501 | { 502 | auto impl = static_cast *>(impl_.get()); 503 | impl->send_request(wsref); 504 | } 505 | 506 | #endif // OMG_DDS_RPC_ENHANCED_PROFILE 507 | 508 | template 509 | bool Requester::receive_nondata_samples(bool enable) 510 | { 511 | auto impl = static_cast *>(impl_.get()); 512 | return impl->receive_nondata_samples(enable); 513 | } 514 | 515 | template 516 | bool Requester::receive_reply( 517 | Sample& reply, 518 | const dds::SampleIdentity & relatedRequestId, 519 | const dds::Duration & timeout) 520 | { 521 | auto impl = static_cast *>(impl_.get()); 522 | return impl->receive_reply(reply, relatedRequestId, timeout); 523 | } 524 | 525 | template 526 | typename Requester::RequestDataWriter 527 | Requester::get_request_datawriter() const 528 | { 529 | auto impl = static_cast *>(impl_.get()); 530 | return impl->get_request_datawriter(); 531 | } 532 | 533 | template 534 | typename Requester::ReplyDataReader 535 | Requester::get_reply_datareader() const 536 | { 537 | auto impl = static_cast *>(impl_.get()); 538 | return impl->get_reply_datareader(); 539 | } 540 | 541 | 542 | template 543 | Requester::~Requester() 544 | { } 545 | 546 | /**************************************************/ 547 | /************** Replier ***************************/ 548 | /**************************************************/ 549 | 550 | 551 | template 552 | Replier::Replier() 553 | : RPCEntity(boost::make_shared>(), 0) 554 | { } 555 | 556 | template 557 | Replier::Replier(const ReplierParams& params) 558 | : RPCEntity(boost::make_shared>(params), 0) 559 | { } 560 | 561 | template 562 | bool Replier::receive_request(Sample & sample, const dds::Duration & timeout) 563 | { 564 | return static_cast *>(impl_.get())->receive_request(sample, timeout); 565 | } 566 | /* 567 | template 568 | void Replier::send_reply_connext( 569 | TRep & reply, 570 | const Sample & related_request_sample) 571 | { 572 | impl_->send_reply_connext(reply, related_request_sample); 573 | } 574 | */ 575 | 576 | template 577 | void Replier::send_reply( 578 | TRep & reply, 579 | const dds::SampleIdentity & identity) 580 | { 581 | static_cast *>(impl_.get())->send_reply(reply, identity); 582 | } 583 | 584 | template 585 | bool Replier::receive_nondata_samples(bool enable) 586 | { 587 | return static_cast *>(impl_.get())->receive_nondata_samples(enable); 588 | } 589 | 590 | template 591 | Replier::~Replier() 592 | { } 593 | 594 | 595 | 596 | } // namespace rpc 597 | } //namespace dds 598 | 599 | #endif // USE_RTI_CONNEXT 600 | -------------------------------------------------------------------------------- /robot-vs2013.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2013 3 | VisualStudioVersion = 12.0.21005.1 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "robot_test", "robot_client-vs2013.vcxproj", "{AF3F3EC2-0479-3DAC-4669-46F09D037424}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug DLL|Win32 = Debug DLL|Win32 10 | Debug|Win32 = Debug|Win32 11 | Release DLL|Win32 = Release DLL|Win32 12 | Release|Win32 = Release|Win32 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 16 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 17 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Debug|Win32.Build.0 = Debug|Win32 19 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 20 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Release DLL|Win32.Build.0 = Release DLL|Win32 21 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Release|Win32.ActiveCfg = Release|Win32 22 | {AF3F3EC2-0479-3DAC-4669-46F09D037424}.Release|Win32.Build.0 = Release|Win32 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /robot-vs2015.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 14 3 | VisualStudioVersion = 14.0.23107.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "robot_test", "robot_client-vs2015.vcxproj", "{AF3F3EC2-0479-3DAC-4669-46F09D037425}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug DLL|Win32 = Debug DLL|Win32 10 | Debug DLL|x64 = Debug DLL|x64 11 | Debug|Win32 = Debug|Win32 12 | Debug|x64 = Debug|x64 13 | Release DLL|Win32 = Release DLL|Win32 14 | Release DLL|x64 = Release DLL|x64 15 | Release|Win32 = Release|Win32 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32 20 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug DLL|Win32.Build.0 = Debug DLL|Win32 21 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 22 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug DLL|x64.Build.0 = Debug DLL|x64 23 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug|Win32.ActiveCfg = Debug|Win32 24 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug|Win32.Build.0 = Debug|Win32 25 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug|x64.ActiveCfg = Debug|x64 26 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Debug|x64.Build.0 = Debug|x64 27 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release DLL|Win32.ActiveCfg = Release DLL|Win32 28 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release DLL|Win32.Build.0 = Release DLL|Win32 29 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release DLL|x64.ActiveCfg = Release DLL|x64 30 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release DLL|x64.Build.0 = Release DLL|x64 31 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release|Win32.ActiveCfg = Release|Win32 32 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release|Win32.Build.0 = Release|Win32 33 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release|x64.ActiveCfg = Release|x64 34 | {AF3F3EC2-0479-3DAC-4669-46F09D037425}.Release|x64.Build.0 = Release|x64 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /robot.idl: -------------------------------------------------------------------------------- 1 | #ifdef INTERFACE 2 | 3 | module robot { 4 | 5 | exception TooFast {}; 6 | 7 | enum Command { START_COMMAND, STOP_COMMAND }; 8 | 9 | struct Status 10 | { 11 | string msg; 12 | }; 13 | 14 | @DDSService 15 | interface RobotControl 16 | { 17 | void command(Command com); 18 | float setSpeed(float speed) raises (TooFast); 19 | float getSpeed(); 20 | void getStatus(out Status status); 21 | }; 22 | 23 | }; //module robot 24 | 25 | #endif // INTERFACE 26 | 27 | #ifdef BASIC 28 | 29 | #include 30 | /******************************************/ 31 | /* Interface Specific Types Below */ 32 | /******************************************/ 33 | 34 | module robot { 35 | 36 | struct TooFast 37 | { 38 | dds::rpc::UnusedMember dummy; 39 | };//@top-level false 40 | 41 | enum Command { START_COMMAND, STOP_COMMAND }; 42 | 43 | struct Status 44 | { 45 | string msg; 46 | };//@top-level false 47 | 48 | struct RobotControl_command_In 49 | { 50 | Command com; 51 | };//@top-level false 52 | 53 | struct RobotControl_setSpeed_In 54 | { 55 | float speed; 56 | };//@top-level false 57 | 58 | struct RobotControl_getSpeed_In 59 | { 60 | dds::rpc::UnusedMember dummy; 61 | };//@top-level false 62 | 63 | struct RobotControl_getStatus_In 64 | { 65 | dds::rpc::UnusedMember dummy; 66 | };//@top-level false 67 | 68 | const long RobotControl_command_Hash = 1; 69 | const long RobotControl_setSpeed_Hash = 2; 70 | const long RobotControl_getSpeed_Hash = 3; 71 | const long RobotControl_getStatus_Hash = 4; 72 | 73 | union RobotControl_Call switch(long) 74 | { 75 | default: 76 | dds::rpc::UnknownOperation unknownOp; 77 | 78 | case RobotControl_command_Hash: 79 | RobotControl_command_In command; 80 | 81 | case RobotControl_setSpeed_Hash: 82 | RobotControl_setSpeed_In setSpeed; 83 | 84 | case RobotControl_getSpeed_Hash: 85 | RobotControl_getSpeed_In getSpeed; 86 | 87 | case RobotControl_getStatus_Hash: 88 | RobotControl_getStatus_In getStatus; 89 | };//@top-level false 90 | 91 | struct RobotControl_Request 92 | { 93 | dds::rpc::RequestHeader header; 94 | RobotControl_Call data; 95 | }; 96 | 97 | /***********************************************/ 98 | /* Reply Types */ 99 | /***********************************************/ 100 | 101 | 102 | struct RobotControl_command_Out 103 | { 104 | dds::rpc::UnusedMember dummy; 105 | };//@top-level false 106 | 107 | struct RobotControl_setSpeed_Out 108 | { 109 | float return_; 110 | };//@top-level false 111 | 112 | struct RobotControl_getSpeed_Out 113 | { 114 | float return_; 115 | };//@top-level false 116 | 117 | const long TooFast_Ex_Hash = 0xAFED; // HASH 118 | 119 | struct RobotControl_getStatus_Out 120 | { 121 | Status status; 122 | };//@top-level false 123 | 124 | union RobotControl_command_Result switch(long) 125 | { 126 | default: 127 | dds::rpc::UnknownException unknownEx; 128 | 129 | case dds::rpc::REMOTE_EX_OK: 130 | RobotControl_command_Out result; 131 | };//@top-level false 132 | 133 | union RobotControl_setSpeed_Result switch(long) 134 | { 135 | default: 136 | dds::rpc::UnknownException unknownEx; 137 | 138 | case dds::rpc::REMOTE_EX_OK: 139 | RobotControl_setSpeed_Out result; 140 | 141 | case TooFast_Ex_Hash: 142 | TooFast toofast_ex; 143 | };//@top-level false 144 | 145 | union RobotControl_getSpeed_Result switch(long) 146 | { 147 | default: 148 | dds::rpc::UnknownException unknownEx; 149 | 150 | case dds::rpc::REMOTE_EX_OK: 151 | RobotControl_getSpeed_Out result; 152 | };//@top-level false 153 | 154 | union RobotControl_getStatus_Result switch(long) 155 | { 156 | default: 157 | dds::rpc::UnknownException unknownEx; 158 | 159 | case dds::rpc::REMOTE_EX_OK: 160 | RobotControl_getStatus_Out result; 161 | };//@top-level false 162 | 163 | union RobotControl_Return switch(long) 164 | { 165 | default: 166 | dds::rpc::UnknownOperation unknownOp; 167 | 168 | case RobotControl_command_Hash: 169 | RobotControl_command_Result command; 170 | 171 | case RobotControl_setSpeed_Hash: 172 | RobotControl_setSpeed_Result setSpeed; 173 | 174 | case RobotControl_getSpeed_Hash: 175 | RobotControl_getSpeed_Result getSpeed; 176 | 177 | case RobotControl_getStatus_Hash: 178 | RobotControl_getStatus_Result getStatus; 179 | };//@top-level false 180 | 181 | struct RobotControl_Reply 182 | { 183 | dds::rpc::ReplyHeader header; 184 | RobotControl_Return data; 185 | }; 186 | 187 | }; // module robot 188 | 189 | #endif // BASIC 190 | 191 | 192 | 193 | #ifdef ENHANCED 194 | 195 | 196 | #endif // ENHANCED 197 | -------------------------------------------------------------------------------- /robot_client-vs2013.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug DLL 6 | Win32 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release DLL 14 | Win32 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | 22 | robot_test 23 | robot_client 24 | {AF3F3EC2-0479-3DAC-4669-46F09D037424} 25 | 26 | 27 | 28 | Application 29 | false 30 | MultiByte 31 | v120 32 | 33 | 34 | Application 35 | false 36 | MultiByte 37 | v120 38 | 39 | 40 | Application 41 | false 42 | MultiByte 43 | v120 44 | 45 | 46 | Application 47 | false 48 | MultiByte 49 | v120 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | <_ProjectFileVersion>10.0.21006.1 69 | .\objs\i86Win32vs2013\ 70 | .\objs\i86Win32vs2013\ 71 | 72 | .\objs\i86Win32vs2013\ 73 | .\objs\i86Win32vs2013\ 74 | 75 | .\objs\i86Win32vs2013\ 76 | .\objs\i86Win32vs2013\ 77 | 78 | .\objs\i86Win32vs2013\ 79 | .\objs\i86Win32vs2013\ 80 | 81 | 82 | 83 | 84 | .\objs\i86Win32vs2013\robot_client.tlb 85 | 86 | 87 | 88 | 89 | Disabled 90 | $(BOOSTHOME);$(NDDSHOME)\include;$(NDDSHOME)\include\ndds;%(AdditionalIncludeDirectories) 91 | OMG_DDS_RPC_REFERENCE_IMPLEMENTATION;OMG_DDS_RPC_BASIC_PROFILE;USE_OPTIONAL_RPC_API;USE_PPLTASKS;USE_RTI_CONNEXT;WIN32;RTI_WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | EnableFastChecks 93 | MultiThreadedDebug 94 | 95 | 96 | 97 | 98 | .\objs\i86Win32vs2013\ 99 | .\objs\i86Win32vs2013\ 100 | .\objs\i86Win32vs2013\ 101 | Level3 102 | true 103 | EditAndContinue 104 | Default 105 | 106 | 107 | _DEBUG;%(PreprocessorDefinitions) 108 | 0x0409 109 | 110 | 111 | libboost_thread-vc120-mt-sgd-1_55.lib;rticonnextmsgcppd.lib;nddscppzd.lib;nddsczd.lib;nddscorezd.lib;netapi32.lib;advapi32.lib;user32.lib;WS2_32.lib;;%(AdditionalDependencies) 112 | .\objs\i86Win32vs2013\robot_test.exe 113 | true 114 | $(BOOSTHOME)\stage\lib;$(NDDSHOME)\lib\i86Win32VS2013;%(AdditionalLibraryDirectories) 115 | true 116 | .\objs\i86Win32vs2013\robot_test.pdb 117 | Console 118 | MachineX86 119 | 120 | 121 | 122 | 123 | .\objs\i86Win32vs2013\robot_client.tlb 124 | 125 | 126 | 127 | 128 | Disabled 129 | $(BOOSTHOME);$(NDDSHOME)\include;$(NDDSHOME)\include\ndds;%(AdditionalIncludeDirectories) 130 | OMG_DDS_RPC_REFERENCE_IMPLEMENTATION;OMG_DDS_RPC_BASIC_PROFILE;USE_OPTIONAL_RPC_API;USE_PPLTASKS;USE_RTI_CONNEXT;NDDS_DLL_VARIABLE;WIN32_LEAN_AND_MEAN;WIN32;RTI_WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 131 | EnableFastChecks 132 | MultiThreadedDebugDLL 133 | 134 | 135 | 136 | 137 | .\objs\i86Win32vs2013\ 138 | .\objs\i86Win32vs2013\ 139 | .\objs\i86Win32vs2013\ 140 | Level3 141 | true 142 | EditAndContinue 143 | Default 144 | 145 | 146 | _DEBUG;%(PreprocessorDefinitions) 147 | 0x0409 148 | 149 | 150 | nddscppd.lib;nddscd.lib;rticonnextmsgcpp.lib;nddscored.lib;netapi32.lib;advapi32.lib;user32.lib;WS2_32.lib;;%(AdditionalDependencies) 151 | .\objs\i86Win32vs2013\robot_test.exe 152 | true 153 | $(NDDSHOME)\lib\i86Win32VS2013;%(AdditionalLibraryDirectories) 154 | true 155 | .\objs\i86Win32vs2013\robot_client.pdb 156 | Console 157 | MachineX86 158 | 159 | 160 | 161 | 162 | .\objs\i86Win32vs2013\robot_client.tlb 163 | 164 | 165 | 166 | 167 | MaxSpeed 168 | OnlyExplicitInline 169 | $(BOOSTHOME);$(NDDSHOME)\include;$(NDDSHOME)\include\ndds;%(AdditionalIncludeDirectories) 170 | OMG_DDS_RPC_REFERENCE_IMPLEMENTATION;USE_OPTIONAL_RPC_API;USE_PPLTASKS;USE_RTI_CONNEXT;WIN32;RTI_WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 171 | true 172 | MultiThreaded 173 | true 174 | 175 | 176 | 177 | 178 | .\objs\i86Win32vs2013\ 179 | .\objs\i86Win32vs2013\ 180 | .\objs\i86Win32vs2013\ 181 | Level3 182 | true 183 | Default 184 | 185 | 186 | NDEBUG;%(PreprocessorDefinitions) 187 | 0x0409 188 | 189 | 190 | libboost_thread-vc120-mt-s-1_55.lib;rticonnextmsgcpp.lib;;nddscppz.lib;nddscz.lib;nddscorez.lib;netapi32.lib;advapi32.lib;user32.lib;WS2_32.lib;;%(AdditionalDependencies) 191 | .\objs\i86Win32vs2013\robot_client.exe 192 | true 193 | $(BOOSTHOME)\stage\lib;$(NDDSHOME)\lib\i86Win32VS2012;%(AdditionalLibraryDirectories) 194 | .\objs\i86Win32vs2013\robot_client.pdb 195 | Console 196 | MachineX86 197 | 198 | 199 | 200 | 201 | .\objs\i86Win32vs2013\robot_client.tlb 202 | 203 | 204 | 205 | 206 | MaxSpeed 207 | OnlyExplicitInline 208 | $(NDDSHOME)\include;$(NDDSHOME)\include\ndds;%(AdditionalIncludeDirectories) 209 | NDDS_DLL_VARIABLE;WIN32_LEAN_AND_MEAN;WIN32;RTI_WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 210 | true 211 | MultiThreadedDLL 212 | true 213 | 214 | 215 | 216 | 217 | .\objs\i86Win32vs2013\ 218 | .\objs\i86Win32vs2013\ 219 | .\objs\i86Win32vs2013\ 220 | Level3 221 | true 222 | Default 223 | 224 | 225 | NDEBUG;%(PreprocessorDefinitions) 226 | 0x0409 227 | 228 | 229 | nddscpp.lib;nddsc.lib;nddscore.lib;netapi32.lib;advapi32.lib;user32.lib;WS2_32.lib;;%(AdditionalDependencies) 230 | .\objs\i86Win32vs2013\robot_client.exe 231 | true 232 | $(NDDSHOME)\lib\i86Win32VS2012;%(AdditionalLibraryDirectories) 233 | .\objs\i86Win32vs2013\robot_client.pdb 234 | Console 235 | MachineX86 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | Disabled 244 | %(AdditionalIncludeDirectories) 245 | %(PreprocessorDefinitions) 246 | EnableFastChecks 247 | MaxSpeed 248 | %(AdditionalIncludeDirectories) 249 | %(PreprocessorDefinitions) 250 | 251 | 252 | 253 | 254 | 255 | Disabled 256 | %(AdditionalIncludeDirectories) 257 | %(PreprocessorDefinitions) 258 | EnableFastChecks 259 | MaxSpeed 260 | %(AdditionalIncludeDirectories) 261 | %(PreprocessorDefinitions) 262 | 263 | 264 | Disabled 265 | %(AdditionalIncludeDirectories) 266 | %(PreprocessorDefinitions) 267 | EnableFastChecks 268 | MaxSpeed 269 | %(AdditionalIncludeDirectories) 270 | %(PreprocessorDefinitions) 271 | 272 | 273 | Disabled 274 | %(AdditionalIncludeDirectories) 275 | %(PreprocessorDefinitions) 276 | EnableFastChecks 277 | MaxSpeed 278 | %(AdditionalIncludeDirectories) 279 | %(PreprocessorDefinitions) 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | -------------------------------------------------------------------------------- /robot_client-vs2013.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | sources 6 | 7 | 8 | sources 9 | 10 | 11 | sources 12 | 13 | 14 | sources 15 | 16 | 17 | sources 18 | 19 | 20 | sources 21 | 22 | 23 | sources 24 | 25 | 26 | sources 27 | 28 | 29 | sources 30 | 31 | 32 | sources 33 | 34 | 35 | sources 36 | 37 | 38 | sources 39 | 40 | 41 | sources 42 | 43 | 44 | 45 | 46 | headers 47 | 48 | 49 | headers 50 | 51 | 52 | headers 53 | 54 | 55 | headers 56 | 57 | 58 | headers 59 | 60 | 61 | headers 62 | 63 | 64 | headers 65 | 66 | 67 | headers 68 | 69 | 70 | headers 71 | 72 | 73 | headers 74 | 75 | 76 | headers 77 | 78 | 79 | headers 80 | 81 | 82 | headers 83 | 84 | 85 | normative 86 | 87 | 88 | normative 89 | 90 | 91 | normative 92 | 93 | 94 | 95 | 96 | {63fe6228-e517-47b2-8567-c0b3fa5d7b2c} 97 | 98 | 99 | {a7833d3e-feb2-402f-8e15-77b7e2939b88} 100 | 101 | 102 | {f19e9deb-ce50-4be4-828d-c2c7a0c6c7f0} 103 | 104 | 105 | -------------------------------------------------------------------------------- /robot_client-vs2013.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 65 client_rr 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /robot_client-vs2015.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | sources 6 | 7 | 8 | sources 9 | 10 | 11 | sources 12 | 13 | 14 | sources 15 | 16 | 17 | sources 18 | 19 | 20 | sources 21 | 22 | 23 | sources 24 | 25 | 26 | sources 27 | 28 | 29 | sources 30 | 31 | 32 | sources 33 | 34 | 35 | sources 36 | 37 | 38 | sources 39 | 40 | 41 | sources 42 | 43 | 44 | 45 | 46 | headers 47 | 48 | 49 | headers 50 | 51 | 52 | headers 53 | 54 | 55 | headers 56 | 57 | 58 | headers 59 | 60 | 61 | headers 62 | 63 | 64 | headers 65 | 66 | 67 | headers 68 | 69 | 70 | headers 71 | 72 | 73 | headers 74 | 75 | 76 | headers 77 | 78 | 79 | headers 80 | 81 | 82 | headers 83 | 84 | 85 | normative 86 | 87 | 88 | normative 89 | 90 | 91 | normative 92 | 93 | 94 | headers 95 | 96 | 97 | 98 | 99 | {63fe6228-e517-47b2-8567-c0b3fa5d7b2c} 100 | 101 | 102 | {a7833d3e-feb2-402f-8e15-77b7e2939b88} 103 | 104 | 105 | {f19e9deb-ce50-4be4-828d-c2c7a0c6c7f0} 106 | 107 | 108 | -------------------------------------------------------------------------------- /robot_func.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "boost/make_shared.hpp" 5 | 6 | #include "RobotControlSupport.h" 7 | 8 | using namespace dds::rpc; 9 | using namespace robot; 10 | 11 | #ifdef RTI_WIN32 12 | #define strcpy(dst, src) strcpy_s(dst, 255, src); 13 | #endif 14 | 15 | static const float MAX_SPEED = 100; 16 | 17 | class MyRobot : public robot::RobotControl 18 | { 19 | float speed_; 20 | Status status_; 21 | 22 | public: 23 | 24 | MyRobot(const char * msg = 0) 25 | : speed_(10) 26 | { 27 | robot::Status_initialize(&status_); 28 | if (msg) 29 | strcpy(status_.msg, msg); 30 | } 31 | 32 | ~MyRobot() 33 | { 34 | robot::Status_finalize(&status_); 35 | } 36 | 37 | void command(const Command & com) override 38 | { 39 | switch (com) 40 | { 41 | case robot::START_COMMAND: 42 | printf("command callback: START_COMMAND\n"); 43 | break; 44 | case robot::STOP_COMMAND: 45 | printf("command callback: STOP_COMMAND\n"); 46 | break; 47 | default: 48 | printf("Unknown\n"); 49 | } 50 | } 51 | 52 | float setSpeed(float speed) override 53 | { 54 | printf("setSpeed = %f\n", speed); 55 | float oldspeed = speed_; 56 | 57 | if (speed <= MAX_SPEED) 58 | speed_ = speed; 59 | else 60 | throw TooFast(); 61 | 62 | return oldspeed; 63 | } 64 | 65 | float getSpeed() override 66 | { 67 | printf("getSpeed\n"); 68 | return speed_; 69 | } 70 | 71 | void getStatus(Status & status) override 72 | { 73 | printf("getStatus\n"); 74 | //FIXME: status = status_; 75 | if (status.msg) 76 | Status_copy(&status, &status_); 77 | } 78 | }; 79 | 80 | void server_func(const std::string & service_name) 81 | { 82 | try { 83 | boost::shared_ptr myrobot1 = 84 | boost::make_shared("Rock-n-Rolling STATUS..."); 85 | 86 | boost::shared_ptr myrobot2 = 87 | boost::make_shared("Cool STATUS..."); 88 | 89 | dds::rpc::Server server; 90 | 91 | RobotControlSupport::Service 92 | robot_service(*myrobot1, 93 | server, 94 | dds::rpc::ServiceParams().service_name(service_name).instance_name("Rock")); 95 | 96 | dds::rpc::ServiceEndpoint se = robot_service; 97 | 98 | while (true) 99 | server.run(dds::Duration::from_seconds(20)); 100 | } 101 | catch (std::exception & ex) 102 | { 103 | printf("Exception in server_func: %s\n", ex.what()); 104 | } 105 | 106 | } 107 | 108 | template 109 | T & remove_const(const T & t) 110 | { 111 | return const_cast(t); 112 | } 113 | 114 | dds::rpc::future speedup_until_maxspeed( 115 | robot::RobotControlSupport::Client & robot_client) 116 | { 117 | static const int increment = 10; 118 | 119 | return 120 | robot_client 121 | .getSpeed_async() 122 | .then([robot_client](future && speed_fut) 123 | { 124 | float speed = speed_fut.get(); 125 | if (speed + increment <= MAX_SPEED) 126 | { 127 | printf("speedup_until_maxspeed: new speed = %f\n", speed + increment); 128 | return remove_const(robot_client).setSpeed_async(speed + increment); 129 | } 130 | else 131 | return dds::rpc::details::make_ready_future(speed); 132 | }) 133 | .then([robot_client](future && speed_fut) { 134 | float speed = speed_fut.get(); 135 | if (speed + increment <= MAX_SPEED) 136 | return speedup_until_maxspeed(remove_const(robot_client)); 137 | else 138 | return dds::rpc::details::make_ready_future(speed); 139 | }); 140 | } 141 | 142 | dds::rpc::future test_recursive( 143 | robot::RobotControlSupport::Client & robot_client) 144 | { 145 | robot_client.setSpeed(0); 146 | 147 | return speedup_until_maxspeed(robot_client); 148 | } 149 | 150 | #ifdef USE_AWAIT 151 | 152 | dds::rpc::future test_iterative_await( 153 | robot::RobotControlSupport::Client & robot_client) 154 | { 155 | static const int increment = 1; 156 | float speed = 0; 157 | 158 | robot_client.setSpeed(0); 159 | 160 | while ((speed = await robot_client.getSpeed_async()) + increment <= MAX_SPEED) 161 | { 162 | printf("test_iterative_await: thread id = %lld\n", RTIOsapiThread_getCurrentThreadID()); 163 | await robot_client.setSpeed_async(speed + increment); 164 | printf("test_iterative_await: current speed = %f, thread id = %lld\n", 165 | speed + increment, RTIOsapiThread_getCurrentThreadID()); 166 | } 167 | } 168 | 169 | #endif // USE_AWAIT 170 | 171 | void test_asynchronous(robot::RobotControlSupport::Client & robot_client) 172 | { 173 | try { 174 | 175 | for (int i = 0; i < 10; i++) 176 | { 177 | robot_client 178 | .getSpeed_async() 179 | .then([robot_client](future && speed_fut) { 180 | printf("Callback1 thread id = %lld\n", RTIOsapiThread_getCurrentThreadID()); 181 | float speed = speed_fut.get(); 182 | printf("test_asynchronous: getSpeed = %f\n", speed); 183 | speed *= 2; 184 | return remove_const(robot_client).setSpeed_async(speed); 185 | }) 186 | .then([](future && speed_fut) { 187 | try { 188 | printf("Callback2 thread id = %lld\n", RTIOsapiThread_getCurrentThreadID()); 189 | float speed = speed_fut.get(); 190 | } 191 | catch (TooFast &) 192 | { 193 | printf("test_asynchronous: Going too fast!\n"); 194 | } 195 | }); 196 | 197 | NDDSUtility::sleep(dds::Duration::from_millis(100)); 198 | } 199 | } 200 | catch (std::exception & ex) 201 | { 202 | printf("Exception in client_func: %s\n", ex.what()); 203 | } 204 | catch (...) 205 | { 206 | printf("test_asynchronous: Unknown exception\n"); 207 | } 208 | } 209 | 210 | void test_synchronous(robot::RobotControlSupport::Client & robot_client) 211 | { 212 | try { 213 | float speed = 1; 214 | 215 | for (int i = 0; i < 10; i++) 216 | { 217 | try 218 | { 219 | robot_client.setSpeed(speed); 220 | speed = robot_client.getSpeed(); 221 | printf("getSpeed = %f\n", speed); 222 | speed *= 2; 223 | //NDDSUtility::sleep(dds::Duration::from_millis(1000)); 224 | } 225 | catch (robot::TooFast &) { 226 | speed = 1; 227 | } 228 | } 229 | } 230 | catch (std::exception & ex) 231 | { 232 | printf("Exception in client_func: %s\n", ex.what()); 233 | } 234 | } 235 | 236 | void test_conversions(robot::RobotControlSupport::Client & robot_client) 237 | { 238 | dds::rpc::ClientEndpoint client_endpoint = robot_client; 239 | auto dw = 240 | client_endpoint.get_request_datawriter(); 241 | 242 | dds::rpc::ServiceProxy sp = client_endpoint; 243 | 244 | robot_client.bind("robot1"); 245 | } 246 | 247 | #ifdef USE_AWAIT 248 | 249 | future test_await(robot::RobotControlSupport::Client & robot_client) 250 | { 251 | robot_client.setSpeed_async(1); 252 | 253 | for (int i = 0; i < 10; i++) 254 | { 255 | float speed = await robot_client.getSpeed_async(); 256 | float oldspeed = await robot_client.setSpeed_async(speed + 2); 257 | assert(speed == oldspeed); 258 | printf("test_await: old speed = %f\n", oldspeed); 259 | } 260 | } 261 | 262 | #endif // USE_AWAIT 263 | 264 | void client_func(const std::string & service_name) 265 | { 266 | try { 267 | robot::RobotControlSupport::Client robot_client; 268 | 269 | NDDSUtility::sleep(dds::Duration::from_millis(1000)); 270 | 271 | test_conversions(robot_client); 272 | test_synchronous(robot_client); 273 | test_asynchronous(robot_client); 274 | test_recursive(robot_client).get(); 275 | 276 | #ifdef USE_AWAIT 277 | //test_await(robot_client).get(); 278 | test_iterative_await(robot_client).get(); 279 | #endif 280 | 281 | printf("Press ENTER to end the program.\n"); 282 | getchar(); 283 | } 284 | catch (...) 285 | { 286 | printf("Exception in main.\n"); 287 | } 288 | } 289 | 290 | -------------------------------------------------------------------------------- /robot_reqrep.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "robotSupport.h" 6 | #include "normative/request_reply.h" 7 | #include "unique_data.h" 8 | 9 | #ifdef RTI_WIN32 10 | #define strcpy(dst, src) strcpy_s(dst, 255, src); 11 | #endif 12 | 13 | using namespace dds::rpc; 14 | using namespace robot; 15 | 16 | void test_synchronous_api( 17 | Requester & requester) 18 | { 19 | helper::unique_data request; 20 | dds::Sample reply_sample; 21 | float speed = 0, oldspeed = 0; 22 | 23 | for (int i = 0; i < 10; i++) 24 | { 25 | request->data._d = RobotControl_getSpeed_Hash; 26 | requester.send_request(*request); 27 | 28 | while (!requester.receive_reply( 29 | reply_sample, 30 | request->header.requestId, 31 | dds::Duration::from_seconds(20))) 32 | { 33 | printf("waiting for reply to getSpeed...\n"); 34 | } 35 | 36 | oldspeed = reply_sample.data().data._u.getSpeed._u.result.return_; 37 | //printf("test_synchronous_api: sn = %d, get speed = %f\n", 38 | // reply_sample.data().header.relatedRequestId.sequence_number.low, 39 | // oldspeed); 40 | 41 | speed = oldspeed + 10; 42 | 43 | request->data._d = RobotControl_setSpeed_Hash; 44 | request->data._u.setSpeed.speed = speed; 45 | 46 | requester.send_request(*request); 47 | while (!requester.receive_reply( 48 | reply_sample, 49 | request->header.requestId, 50 | dds::Duration::from_seconds(20))) 51 | { 52 | // synchronous 53 | printf("test_synchronous_api: waiting for reply to setSpeed...\n"); 54 | } 55 | if (reply_sample.data().data._u.setSpeed._d == robot::TooFast_Ex_Hash) 56 | { 57 | printf("test_synchronous_api: Going too fast.\n"); 58 | } 59 | else 60 | { 61 | oldspeed = reply_sample.data().data._u.setSpeed._u.result.return_; 62 | assert(oldspeed == (speed - 10)); 63 | } 64 | } 65 | } 66 | 67 | void test_synchronous_future( 68 | Requester & requester) 69 | { 70 | helper::unique_data request; 71 | dds::rpc::future> reply_future; 72 | dds::Sample reply_sample; 73 | float speed = 0, oldspeed = 0; 74 | 75 | 76 | for (int i = 0; i < 10; i++) 77 | { 78 | try { 79 | request->data._d = RobotControl_getSpeed_Hash; 80 | reply_future = requester.send_request_async(*request); 81 | 82 | reply_sample = reply_future.get(); // synchronous 83 | oldspeed = reply_sample.data().data._u.getSpeed._u.result.return_; 84 | 85 | //printf("test_synchronous_future: sn = %d, get speed = %f\n", 86 | // reply_sample.data().header.relatedRequestId.sequence_number.low, 87 | // oldspeed); 88 | 89 | speed = oldspeed + 10; 90 | 91 | request->data._d = RobotControl_setSpeed_Hash; 92 | request->data._u.setSpeed.speed = speed; 93 | 94 | reply_future = requester.send_request_async(*request); 95 | reply_sample = reply_future.get(); // synchronous 96 | 97 | if (reply_sample.data().data._u.setSpeed._d == robot::TooFast_Ex_Hash) 98 | { 99 | printf("test_synchronous_future: Going too fast!\n"); 100 | } 101 | else 102 | { 103 | oldspeed = reply_sample.data().data._u.setSpeed._u.result.return_; 104 | assert(oldspeed == (speed - 10)); 105 | } 106 | } 107 | catch (std::runtime_error & ex) 108 | { 109 | printf("test_synchronous_future: Runtime exception: %s\n", ex.what()); 110 | } 111 | } 112 | } 113 | 114 | void test_asynchronous_getSpeed( 115 | Requester & requester) 116 | { 117 | helper::unique_data request; 118 | auto speed_lambda = [](future && maybe_speed) 119 | { 120 | try { 121 | float speed = maybe_speed.get(); 122 | printf("test_asynchronous_getSpeed: getSpeed = %f\n", speed); 123 | } 124 | catch (std::runtime_error & ex) { 125 | printf("test_asynchronous_getSpeed: Runtime exception: %s\n", ex.what()); 126 | //throw; 127 | } 128 | catch (std::exception & ex) { 129 | printf("test_asynchronous_getSpeed: generic exception: %s\n", ex.what()); 130 | //throw; 131 | } 132 | catch (...) { 133 | printf("test_asynchronous_getSpeed: Unknown exception\n"); 134 | } 135 | }; 136 | 137 | #ifdef USE_PPLTASKS 138 | 139 | for (int i = 0; i < 10; i++) 140 | { 141 | request->data._d = RobotControl_getSpeed_Hash; 142 | 143 | requester 144 | .send_request_async(*request) 145 | .then([i](future> && reply_fut) 146 | { 147 | dds::Sample reply_sample = reply_fut.get(); 148 | return reply_sample.data().data._u.getSpeed._u.result.return_; 149 | }) 150 | .then(speed_lambda); 151 | // what happens if speed_lambda throws? 152 | } 153 | 154 | #endif // USE_PPLTASKS 155 | } 156 | 157 | void test_asynchronous_race( 158 | Requester & requester) 159 | { 160 | helper::unique_data request; 161 | 162 | #ifdef USE_PPLTASKS 163 | for (int i = 0; i < 10 ; ++i) 164 | { 165 | request->data._d = robot::RobotControl_getSpeed_Hash; 166 | 167 | requester 168 | .send_request_async(*request) 169 | .then([requester] (future> && reply_fut) 170 | { 171 | dds::Sample reply_sample = reply_fut.get(); 172 | float speed = reply_sample.data().data._u.getSpeed._u.result.return_; 173 | helper::unique_data request; 174 | request->data._d = robot::RobotControl_setSpeed_Hash; 175 | request->data._u.setSpeed.speed = speed + 10; 176 | return const_cast &>(requester).send_request_async(*request); 177 | }) 178 | .then([](future> && reply_fut) 179 | { 180 | try { 181 | dds::Sample reply_sample = reply_fut.get(); 182 | 183 | if (reply_sample.data().data._d == robot::RobotControl_setSpeed_Hash) 184 | { 185 | if(reply_sample.data().data._u.setSpeed._d == RETCODE_OK) 186 | { 187 | float oldspeed = reply_sample.data().data._u.setSpeed._u.result.return_; 188 | printf("test_asynchronous_race: old speed = %f\n", oldspeed); 189 | } 190 | else if (reply_sample.data().data._u.setSpeed._d == TooFast_Ex_Hash) 191 | { 192 | printf("test_asynchronous_race: Going too fast!\n"); 193 | } 194 | else 195 | { 196 | printf("test_asynchronous_race: Server-side exception\n"); 197 | } 198 | } 199 | } 200 | catch (std::runtime_error & ex) { 201 | printf("test_asynchronous_race: Run-time exception: %s\n", ex.what()); 202 | } 203 | catch (std::exception & ex) { 204 | printf("test_asynchronous_race: Generic exception: %s\n", ex.what()); 205 | } 206 | catch (...) { 207 | printf("test_asynchronous_race: Unknown exception\n"); 208 | } 209 | }); 210 | } 211 | #endif // USE_PPLTASKS 212 | } 213 | 214 | #ifdef USE_AWAIT 215 | 216 | future test_await( 217 | Requester & requester) 218 | { 219 | helper::unique_data request; 220 | float speed = 0; 221 | request->data._d = robot::RobotControl_setSpeed_Hash; 222 | request->data._u.setSpeed.speed = speed; 223 | requester.send_request_async(*request); 224 | 225 | printf("before. threadid = %lld\n", RTIOsapiThread_getCurrentThreadID()); 226 | while (speed < 100) 227 | { 228 | request->data._d = robot::RobotControl_getSpeed_Hash; 229 | dds::Sample reply = await requester.send_request_async(*request); 230 | speed = reply.data().data._u.getSpeed._u.result.return_; 231 | printf("test_await: current speed = %f threadid = %lld\n", 232 | speed, 233 | RTIOsapiThread_getCurrentThreadID()); 234 | 235 | request->data._d = robot::RobotControl_setSpeed_Hash; 236 | request->data._u.setSpeed.speed = speed + 10; 237 | await requester.send_request_async(*request); 238 | } 239 | printf("after. threadid = %lld\n", RTIOsapiThread_getCurrentThreadID()); 240 | } 241 | 242 | #endif // USE_AWAIT 243 | 244 | void wait(int seconds) 245 | { 246 | printf("Waiting %d seconds before testing await.\n", seconds); 247 | for (int i = 0; i < seconds; i++) 248 | { 249 | NDDSUtility::sleep(dds::Duration::from_seconds(1)); 250 | printf("."); 251 | } 252 | } 253 | 254 | void client_rr(const std::string & service_name) 255 | { 256 | try { 257 | // DomainParticipant construction is optional. 258 | 259 | RequesterParams requester_params = 260 | dds::rpc::RequesterParams() 261 | .service_name(service_name); 262 | 263 | Requester 264 | requester(requester_params); 265 | 266 | NDDSUtility::sleep(dds::Duration::from_seconds(1)); 267 | 268 | test_synchronous_api(requester); 269 | test_synchronous_future(requester); 270 | test_asynchronous_getSpeed(requester); 271 | test_asynchronous_race(requester); 272 | 273 | #ifdef USE_AWAIT 274 | wait(3); 275 | test_await(requester).get(); 276 | 277 | #endif // USE_AWAIT 278 | 279 | //printf("Press ENTER to end the program.\n"); 280 | //getchar(); 281 | 282 | } 283 | catch (std::exception & ex) 284 | { 285 | printf("Exception in client_rr: %s\n", ex.what()); 286 | } 287 | catch (...) 288 | { 289 | printf("Unknown exception in client_rr\n"); 290 | } 291 | 292 | } 293 | 294 | void print_request(const RobotControl_Request & request) 295 | { 296 | switch (request.data._d) 297 | { 298 | case RobotControl_command_Hash: 299 | switch (request.data._u.command.com) 300 | { 301 | case robot::START_COMMAND: 302 | printf("START_COMMAND\n"); 303 | break; 304 | case robot::STOP_COMMAND: 305 | printf("START_COMMAND\n"); 306 | break; 307 | default: 308 | printf("Unknown\n"); 309 | } 310 | break; 311 | case RobotControl_setSpeed_Hash: 312 | printf("setSpeed = %f\n", request.data._u.setSpeed.speed); 313 | break; 314 | case RobotControl_getSpeed_Hash: 315 | printf("getSpeed\n"); 316 | break; 317 | case RobotControl_getStatus_Hash: 318 | printf("getStatus\n"); 319 | break; 320 | } 321 | } 322 | 323 | dds::SampleIdentity to_rpc_sample_identity(const DDS::SampleIdentity_t & inid) 324 | { 325 | static_assert(sizeof(dds::SampleIdentity) == sizeof(DDS::SampleIdentity_t), 326 | "Sizes of two SampleIdentity don't match!"); 327 | 328 | dds::SampleIdentity outid; 329 | memcpy(&outid, &inid, sizeof(SampleIdentity_t)); 330 | return outid; 331 | } 332 | 333 | class Robot 334 | { 335 | float speed; 336 | static const int SPEED_LIMIT = 100; 337 | 338 | public: 339 | Robot() : speed(0) 340 | { } 341 | 342 | helper::unique_data process_request( 343 | const dds::Sample & request) 344 | { 345 | helper::unique_data reply; 346 | float oldspeed = speed; 347 | 348 | switch (request.data().data._d) 349 | { 350 | case RobotControl_command_Hash: 351 | switch (request.data().data._u.command.com) 352 | { 353 | case robot::START_COMMAND: 354 | case robot::STOP_COMMAND: 355 | reply->data._d = RobotControl_command_Hash; 356 | reply->data._u.command._d = RETCODE_OK; 357 | reply->data._u.command._u.result.dummy = 0x0; 358 | break; 359 | default: 360 | reply->data._d = RobotControl_command_Hash; 361 | reply->data._u.command._d = RETCODE_ERROR; 362 | reply->data._u.command._u.unknownEx = RETCODE_ERROR; 363 | } 364 | break; 365 | case RobotControl_setSpeed_Hash: 366 | if (request.data().data._u.setSpeed.speed > SPEED_LIMIT) 367 | { 368 | reply->data._d = RobotControl_setSpeed_Hash; 369 | reply->data._u.setSpeed._d = robot::TooFast_Ex_Hash; 370 | reply->data._u.setSpeed._u.toofast_ex = TooFast(); 371 | speed = 0; 372 | } 373 | else 374 | { 375 | speed = request.data().data._u.setSpeed.speed; 376 | reply->data._d = RobotControl_setSpeed_Hash; 377 | reply->data._u.setSpeed._d = RETCODE_OK; 378 | reply->data._u.setSpeed._u.result.return_ = oldspeed; 379 | } 380 | break; 381 | case RobotControl_getSpeed_Hash: 382 | reply->data._d = RobotControl_getSpeed_Hash; 383 | reply->data._u.getSpeed._d = RETCODE_OK; 384 | reply->data._u.getSpeed._u.result.return_ = speed; 385 | break; 386 | case RobotControl_getStatus_Hash: 387 | reply->data._d = RobotControl_getStatus_Hash; 388 | reply->data._u.getStatus._d = RETCODE_OK; 389 | strcpy(reply->data._u.getStatus._u.result.status.msg, "Good Status"); 390 | break; 391 | } 392 | 393 | return reply; 394 | } 395 | }; 396 | 397 | void server_rr(const std::string & service_name) 398 | { 399 | // DomainParticipant construction is optional. 400 | 401 | ReplierParams replier_params = 402 | dds::rpc::ReplierParams() 403 | .service_name(service_name); 404 | 405 | Robot robot; 406 | 407 | Replier 408 | replier(replier_params); 409 | 410 | NDDSUtility::sleep(dds::Duration::from_millis(2000)); 411 | 412 | while (true) 413 | { 414 | dds::Sample request; 415 | 416 | if (replier.receive_request(request, 417 | dds::Duration::from_seconds(60))) 418 | { 419 | print_request(request.data()); 420 | 421 | NDDSUtility::sleep(dds::Duration::from_millis(50)); 422 | helper::unique_data 423 | reply(robot.process_request(request)); 424 | 425 | replier.send_reply(*reply, to_rpc_sample_identity(request.identity())); 426 | } 427 | else 428 | printf("timeout or invalid data. Ignoring...\n"); 429 | } 430 | } 431 | -------------------------------------------------------------------------------- /robot_test.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "common.h" 9 | 10 | void client_rr(const std::string & service_name); 11 | void server_rr(const std::string & service_name); 12 | 13 | void client_func(const std::string & service_name); 14 | void server_func(const std::string & service_name); 15 | 16 | void usage() 17 | { 18 | printf("Usage: robot_test domainid [client_rr|client_func|server_rr|server_func]\n"); 19 | } 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | try { 24 | int domainid = 65; 25 | std::string service_name = "RobotControl"; 26 | 27 | /*NDDSConfigLogger::get_instance()->set_verbosity_by_category( 28 | NDDS_CONFIG_LOG_CATEGORY_API, 29 | NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); 30 | */ 31 | 32 | if (argc == 3) 33 | { 34 | domainid = atoi(argv[1]); 35 | DDSDomainParticipant * default_participant = 36 | dds::rpc::details::DefaultDomainParticipant::singleton().set_domainid(domainid).get(); 37 | 38 | if (strcmp(argv[2], "client_rr") == 0) 39 | client_rr(service_name); 40 | else if (strcmp(argv[2], "server_rr") == 0) 41 | server_rr(service_name); 42 | else if (strcmp(argv[2], "client_func") == 0) 43 | client_func(service_name); 44 | else if (strcmp(argv[2], "server_func") == 0) 45 | server_func(service_name); 46 | else 47 | usage(); 48 | } 49 | else 50 | usage(); 51 | 52 | return 0; 53 | } 54 | catch (std::exception & ex) 55 | { 56 | printf("Exception in main: %s\n", ex.what()); 57 | } 58 | catch (...) 59 | { 60 | printf("Unknown exception in main\n"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /rpc_types.idl: -------------------------------------------------------------------------------- 1 | #ifdef BASIC 2 | 3 | module dds { 4 | 5 | #ifdef REDEFINE_DDS_TYPES 6 | 7 | // The following DDS related types are 8 | // borrowed from the RTPS v1.2 specification 9 | typedef octet GuidPrefix_t[12]; 10 | 11 | struct EntityId_t 12 | { 13 | octet entityKey[3]; 14 | octet entityKind; 15 | };//@top-level false 16 | 17 | struct GUID_t 18 | { 19 | GuidPrefix_t guidPrefix; 20 | EntityId_t entityId; 21 | };//@top-level false 22 | 23 | struct SequenceNumber_t 24 | { 25 | long high; 26 | unsigned long low; 27 | };//@top-level false 28 | 29 | #endif // REDEFINE_DDS_TYPES 30 | 31 | struct SampleIdentity 32 | { 33 | GUID_t writer_guid; 34 | SequenceNumber_t sequence_number; 35 | };//@top-level false 36 | 37 | module rpc { 38 | 39 | typedef octet UnknownOperation; 40 | typedef octet UnknownException; 41 | typedef octet UnusedMember; 42 | 43 | enum RemoteExceptionCode_t 44 | { 45 | REMOTE_EX_OK, 46 | REMOTE_EX_UNSUPPORTED, 47 | REMOTE_EX_INVALID_ARGUMENT, 48 | REMOTE_EX_OUT_OF_RESOURCES, 49 | REMOTE_EX_UNKNOWN_OPERATION, 50 | REMOTE_EX_UNKNOWN_EXCEPTION 51 | }; 52 | 53 | struct RequestHeader 54 | { 55 | dds::SampleIdentity requestId; 56 | string<255> instanceName; 57 | };//@top-level false 58 | 59 | struct ReplyHeader 60 | { 61 | dds::SampleIdentity relatedRequestId; 62 | dds::rpc::RemoteExceptionCode_t remoteEx; 63 | };//@top-level false 64 | 65 | }; // module rpc 66 | 67 | }; // module dds 68 | 69 | #endif // BASIC 70 | 71 | -------------------------------------------------------------------------------- /unique_data.h: -------------------------------------------------------------------------------- 1 | #ifndef UNIQUE_DATA_H 2 | #define UNIQUE_DATA_H 3 | 4 | #include 5 | 6 | namespace helper { 7 | 8 | template 9 | class unique_data 10 | { 11 | T * ptr_; 12 | 13 | unique_data(const unique_data &); 14 | unique_data & operator = (const unique_data &); 15 | 16 | public: 17 | unique_data() 18 | : ptr_(T::TypeSupport::create_data()) 19 | { 20 | if (!ptr_) 21 | throw std::runtime_error("Can't create data"); 22 | } 23 | 24 | unique_data(unique_data && ud) 25 | : ptr_(ud.ptr_) 26 | { 27 | ud.ptr_ = 0; 28 | } 29 | 30 | unique_data & operator = (unique_data && ud) 31 | { 32 | std::swap(ptr_, ud.ptr_); 33 | return *this; 34 | } 35 | 36 | unique_data(T *t) 37 | : ptr_(t) 38 | {} 39 | 40 | T * operator -> () { 41 | return ptr_; 42 | } 43 | 44 | T * get() { 45 | return ptr_; 46 | } 47 | 48 | T & operator * () { 49 | return *ptr_; 50 | } 51 | 52 | ~unique_data() { 53 | if (ptr_) 54 | T::TypeSupport::delete_data(ptr_); 55 | } 56 | }; 57 | 58 | } // namespace helper 59 | 60 | #endif // UNIQUE_DATA_H 61 | -------------------------------------------------------------------------------- /vendor_dependent.h: -------------------------------------------------------------------------------- 1 | #ifndef VENDOR_DEPENDENT_H 2 | #define VENDOR_DEPENDENT_H 3 | 4 | struct DDS_Duration_t; 5 | struct DDS_SampleInfo; 6 | struct DDS_SampleInfoSeq; 7 | struct DDS_DataReaderQos; 8 | struct DDS_DataWriterQos; 9 | struct DDS_SampleIdentity_t; 10 | 11 | class DDSDomainParticipant; 12 | class DDSPublisher; 13 | class DDSSubscriber; 14 | 15 | namespace boost { 16 | 17 | template 18 | class shared_ptr; 19 | 20 | } // namespace boost 21 | 22 | namespace connext { 23 | 24 | template 25 | class Sample; 26 | 27 | template 28 | class SampleRef; 29 | 30 | template 31 | class WriteSample; 32 | 33 | template 34 | class WriteSampleRef; 35 | 36 | template 37 | class LoanedSamples; 38 | 39 | template 40 | class SampleIterator; 41 | 42 | template 43 | struct dds_type_traits; 44 | 45 | } // namespace connext 46 | 47 | namespace dds { 48 | 49 | typedef ::DDS_Duration_t Duration; 50 | typedef ::DDS_SampleInfo SampleInfo; 51 | typedef ::DDS_SampleInfoSeq SampleInfoSeq; 52 | 53 | using connext::Sample; 54 | using connext::SampleRef; 55 | using connext::WriteSample; 56 | using connext::WriteSampleRef; 57 | using connext::LoanedSamples; 58 | using connext::SampleIterator; 59 | 60 | template 61 | struct dds_type_traits 62 | { 63 | typedef typename T::DataReader* DataReader; 64 | typedef typename T::DataWriter* DataWriter; 65 | 66 | typedef SampleRef SampleRefType; 67 | typedef SampleRef SampleIteratorValueType; 68 | typedef SampleRef ConstSampleIteratorValueType; 69 | typedef LoanedSamples LoanedSamplesType; 70 | typedef SampleIterator iterator; 71 | typedef SampleIterator const_iterator; 72 | }; 73 | 74 | struct dds_entity_traits 75 | { 76 | typedef ::DDSDomainParticipant* DomainParticipant; 77 | typedef ::DDSPublisher* Publisher; 78 | typedef ::DDSSubscriber* Subscriber; 79 | typedef ::DDS_DataReaderQos const * DataReaderQos; 80 | typedef ::DDS_DataWriterQos const * DataWriterQos; 81 | }; 82 | 83 | template 84 | class SharedSamples; 85 | 86 | namespace rpc { 87 | 88 | class RPCEntity; 89 | class ServiceProxy; 90 | class RequesterParams; 91 | class ReplierParams; 92 | class ServiceParams; 93 | class ClientParams; 94 | class ServerParams; 95 | class ServiceEndpoint; 96 | class Server; 97 | 98 | template 99 | class Requester; 100 | 101 | template 102 | class Replier; 103 | 104 | template 105 | class shared_future; 106 | 107 | namespace details { 108 | 109 | class ServerImpl; 110 | class ServiceParamsImpl; 111 | class ClientParamsImpl; 112 | class ServerParamsImpl; 113 | class ServiceEndpointImpl; 114 | class RequesterParamsImpl; 115 | class ReplierParamsImpl; 116 | class ServiceProxyImpl; 117 | class RPCEntityImpl; 118 | 119 | template 120 | class RequesterImpl; 121 | 122 | template 123 | class ClientImpl; 124 | 125 | template 126 | class ReplierImpl; 127 | 128 | template 129 | struct Unwrapper; 130 | 131 | template 132 | struct vendor_dependent; 133 | 134 | template <> 135 | struct vendor_dependent 136 | { 137 | typedef boost::shared_ptr type; 138 | }; 139 | 140 | template <> 141 | struct vendor_dependent 142 | { 143 | typedef boost::shared_ptr type; 144 | }; 145 | 146 | template <> 147 | struct vendor_dependent 148 | { 149 | typedef boost::shared_ptr type; 150 | }; 151 | 152 | template <> 153 | struct vendor_dependent 154 | { 155 | typedef boost::shared_ptr type; 156 | }; 157 | 158 | template <> 159 | struct vendor_dependent 160 | { 161 | typedef boost::shared_ptr type; 162 | }; 163 | 164 | template <> 165 | struct vendor_dependent 166 | { 167 | typedef boost::shared_ptr type; 168 | }; 169 | 170 | template <> 171 | struct vendor_dependent 172 | { 173 | typedef boost::shared_ptr type; 174 | }; 175 | 176 | template <> 177 | struct vendor_dependent 178 | { 179 | typedef boost::shared_ptr type; 180 | }; 181 | 182 | template 183 | struct vendor_dependent> 184 | { 185 | typedef boost::shared_ptr> type; 186 | }; 187 | 188 | template 189 | struct vendor_dependent> 190 | { 191 | typedef boost::shared_ptr> type; 192 | }; 193 | 194 | } // namespace details 195 | } // namespace rpc 196 | } // namespace dds 197 | 198 | 199 | 200 | #include "rpc_types.h" 201 | #include "boost/shared_ptr.hpp" 202 | #include "ndds/ndds_requestreply_cpp.h" 203 | #include "future_adapter.hpp" 204 | 205 | #endif // VENDOR_DEPENDENT_H 206 | --------------------------------------------------------------------------------