From b8fd26fea77662802e62660460fdbf5f5dea990c Mon Sep 17 00:00:00 2001 From: Jackie Date: Thu, 25 Jun 2015 17:34:06 -0700 Subject: [PATCH 01/34] Added realtime-performant examples --- realtime/CMakeLists.txt | 21 +++ realtime/check_status.h | 46 +++++ realtime/dds_intraproc.cpp | 320 ++++++++++++++++++++++++++++++++++ realtime/dds_lmp.cpp | 116 ++++++++++++ realtime/dds_lms.cpp | 140 +++++++++++++++ realtime/idl/LargeMsg.idl | 7 + realtime/msg/LargeMessage.msg | 2 + 7 files changed, 652 insertions(+) create mode 100644 realtime/CMakeLists.txt create mode 100644 realtime/check_status.h create mode 100644 realtime/dds_intraproc.cpp create mode 100644 realtime/dds_lmp.cpp create mode 100644 realtime/dds_lms.cpp create mode 100644 realtime/idl/LargeMsg.idl create mode 100644 realtime/msg/LargeMessage.msg diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt new file mode 100644 index 0000000..7698325 --- /dev/null +++ b/realtime/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8) +project(large_message_cpp) + +find_package(opensplice REQUIRED) +include_directories(${OPENSPLICE_INCLUDE_DIRS}) + +ospl_add_idl(idl/LargeMsg.idl) + +add_executable(dds_lms dds_lms.cpp) +target_link_libraries(dds_lms ${OPENSPLICE_LIBRARIES}) + +add_executable(dds_lmp dds_lmp.cpp) +target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES}) + +find_package(Threads) +if(NOT Threads_FOUND) + message(WARNING "Pthread not found. Real-time intra-process pub/sub example will not be built.") +elseif(Threads_FOUND) + add_executable(dds_intraproc dds_intraproc.cpp) + target_link_libraries(dds_intraproc ${OPENSPLICE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +endif() diff --git a/realtime/check_status.h b/realtime/check_status.h new file mode 100644 index 0000000..2f5b804 --- /dev/null +++ b/realtime/check_status.h @@ -0,0 +1,46 @@ +#ifndef __CHECKSTATUS_H__ +#define __CHECKSTATUS_H__ + +#include "ccpp_dds_dcps.h" +#include + +const char *RetCodeName[13] = { + "DDS_RETCODE_OK", + "DDS_RETCODE_ERROR", + "DDS_RETCODE_UNSUPPORTED", + "DDS_RETCODE_BAD_PARAMETER", + "DDS_RETCODE_PRECONDITION_NOT_MET", + "DDS_RETCODE_OUT_OF_RESOURCES", + "DDS_RETCODE_NOT_ENABLED", + "DDS_RETCODE_IMMUTABLE_POLICY", + "DDS_RETCODE_INCONSISTENT_POLICY", + "DDS_RETCODE_ALREADY_DELETED", + "DDS_RETCODE_TIMEOUT", + "DDS_RETCODE_NO_DATA", + "DDS_RETCODE_ILLEGAL_OPERATION" +}; + +const char * getErrorName(DDS::ReturnCode_t status) +{ + return RetCodeName[status]; +} + +void checkStatus(DDS::ReturnCode_t status, const char *info) +{ + if (status != DDS::RETCODE_OK && status != DDS::RETCODE_NO_DATA) + { + std::cerr << "Error in " << info << ": " << getErrorName(status) << std::endl; + exit (1); + } +} + +void checkHandle(void *handle, const char *info) +{ + if (!handle) + { + std::cerr << "Error in " << info << ": Creation failed: invalid handle" << std::endl; + exit (1); + } +} + +#endif diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp new file mode 100644 index 0000000..d42dcbc --- /dev/null +++ b/realtime/dds_intraproc.cpp @@ -0,0 +1,320 @@ +#include +#include + +#include "ccpp_dds_dcps.h" +#include "check_status.h" + +#include "ccpp_LargeMsg.h" + +bool running = true; + +static void catch_function(int signo) { + running = false; + std::cout << "Catching Ctrl-C, shutting down..." << std::endl; +} + +static void setprio(int prio, int sched) +{ + struct sched_param param; + // Set realtime priority for this thread + param.sched_priority = prio; + if (sched_setscheduler(0, sched, ¶m) < 0) + perror("sched_setscheduler"); +} + +static void start_rt_thread(void *(*f)(void*)) +{ + pthread_t thread; + pthread_attr_t attr; + + /* init to default values */ + if (pthread_attr_init(&attr)) + { + fprintf(stderr, "Couldn't initialize pthread to default value"); + exit(1); + } + + /* Set the requested stacksize for this thread */ + /*if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + MAX_SAFE_STACK)) + { + fprintf(stderr, "Couldn't set requested stack size for pthread"); + exit(1); + }*/ + + /* And finally start the actual thread */ + pthread_create(&thread, &attr, f, NULL); +} + +void *publisher_thread(void *unused) +{ + setprio(80, SCHED_RR); + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + std::cout << "Creating domain participant in publisher" << std::endl; + DDS::DomainParticipant_var participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + DDS::ReturnCode_t status; + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + char * large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Publisher's QoS */ + DDS::PublisherQos pub_qos; + status = participant->get_default_publisher_qos(pub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); + pub_qos.partition.name.length(1); + pub_qos.partition.name[0] = partition_name; + + /* Create the publisher */ + DDS::Publisher_var publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); + checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); + + /* Create the Topic */ + DDS::Topic_var large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic DataWriter */ + DDS::DataWriter_var topic_writer = publisher->create_datawriter( + large_message_topic.in(), + DATAWRITER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); + + /* Narrow the Topic DataWriter to be only for LargeMessage */ + LargeMsg::LargeMessageDataWriter_var data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); + checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); + + /* Send some large messages */ + std::cout << "Sending LargeMessage's" << std::endl; + LargeMsg::LargeMessage * msg; + msg = new LargeMsg::LargeMessage(); + msg->content = std::string(pow(2, 20), '.').c_str(); // ~8.39 million characters + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 1000000; + for (int i = 0; i < 290; ++i) + { + checkHandle(msg, "new LargeMsg::LargeMessage"); + + msg->seq = i; + + DDS::InstanceHandle_t instance_handle = data_writer->register_instance(*msg); + + status = data_writer->write(*msg, instance_handle); + checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + + clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); + + } + delete msg; + + std::cout << "Finished" << std::endl; + + getchar(); + + /* Shutdown */ + { + status = publisher->delete_datawriter(data_writer.in()); + checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + + status = participant->delete_publisher(publisher.in()); + checkStatus(status, "DDS::DomainParticipant::delete_publisher"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } + return NULL; +} + +void *subscriber_thread(void *unused) +{ + setprio(80, SCHED_RR); + /* Register a signal handler so DDS doesn't just sit there... */ + if (signal(SIGINT, catch_function) == SIG_ERR) + { + fputs("An error occurred while setting a signal handler.\n", stderr); + return NULL; + } + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + std::cout << "Creating domain participant in subscriber" << std::endl; + DDS::DomainParticipant_var participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + DDS::ReturnCode_t status; + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + char * large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Subscribers's QoS */ + DDS::SubscriberQos sub_qos; + status = participant->get_default_subscriber_qos(sub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); + sub_qos.partition.name.length(1); + sub_qos.partition.name[0] = partition_name; + + /* Create the subscriber */ + DDS::Subscriber_var subscriber = participant->create_subscriber( + sub_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); + + /* Create the Topic */ + DDS::Topic_var large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic specific DataReader */ + DDS::DataReader_var topic_reader = subscriber->create_datareader( + large_message_topic.in(), + DATAREADER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); + + /* Narrow topic_reader down to LargeMessage specific DataReader */ + LargeMsg::LargeMessageDataReader_var data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); + checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); + + LargeMsg::LargeMessageSeq_var large_msg_seq = new LargeMsg::LargeMessageSeq(); + DDS::SampleInfoSeq_var sample_info_seq = new DDS::SampleInfoSeq(); + + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 1000000; + std::cout << "Polling DataReader..." << std::endl; + while (running) + { + status = data_reader->take( + large_msg_seq, + sample_info_seq, + DDS::LENGTH_UNLIMITED, + DDS::ANY_SAMPLE_STATE, + DDS::ANY_VIEW_STATE, + DDS::ALIVE_INSTANCE_STATE + ); + checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); + + for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) + { + LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); + std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + } + + status = data_reader->return_loan(large_msg_seq, sample_info_seq); + checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); + + /* Sleep for some amount of time, as not to consume too much CPU cycles. */ +#if defined _WIN32 + Sleep(100); +#else + clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); +#endif + } + + /* Shutdown */ + { + status = participant->delete_subscriber(subscriber.in()); + checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } + return NULL; +} + +int main(int argc, char *argv[]) +{ + struct timespec t; + + setprio(80, SCHED_RR); + + start_rt_thread(&subscriber_thread); + start_rt_thread(&publisher_thread); + + // Set priority for the main thread (monitor) + setprio(60, SCHED_RR); + + t.tv_sec = 0; + t.tv_nsec = 500000; + + // Main thread polls at a regular interval + while (1) + { + // Sleep for 500 ms + clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); + } +} diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp new file mode 100644 index 0000000..dbcef7c --- /dev/null +++ b/realtime/dds_lmp.cpp @@ -0,0 +1,116 @@ +#include "ccpp_dds_dcps.h" +#include "check_status.h" + +#include "ccpp_LargeMsg.h" + +int main(int argc, char *argv[]) +{ + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + DDS::DomainParticipant_var participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + DDS::ReturnCode_t status; + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + char * large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Publisher's QoS */ + DDS::PublisherQos pub_qos; + status = participant->get_default_publisher_qos(pub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); + pub_qos.partition.name.length(1); + pub_qos.partition.name[0] = partition_name; + + /* Create the publisher */ + DDS::Publisher_var publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); + checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); + + /* Create the Topic */ + DDS::Topic_var large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic DataWriter */ + DDS::DataWriter_var topic_writer = publisher->create_datawriter( + large_message_topic.in(), + DATAWRITER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); + + /* Narrow the Topic DataWriter to be only for LargeMessage */ + LargeMsg::LargeMessageDataWriter_var data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); + checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); + + /* Send some large messages */ + std::cout << "Sending LargeMessage's" << std::endl; + LargeMsg::LargeMessage * msg; + msg = new LargeMsg::LargeMessage(); + msg->content = std::string(pow(2, 20), '.').c_str(); // ~8.39 million characters + for (int i = 0; i < 290; ++i) + { + checkHandle(msg, "new LargeMsg::LargeMessage"); + + msg->seq = i; + + DDS::InstanceHandle_t instance_handle = data_writer->register_instance(*msg); + + status = data_writer->write(*msg, instance_handle); + checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + + usleep(100000); + + } + delete msg; + + std::cout << "Finished" << std::endl; + + getchar(); + + /* Shutdown */ + { + status = publisher->delete_datawriter(data_writer.in()); + checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + + status = participant->delete_publisher(publisher.in()); + checkStatus(status, "DDS::DomainParticipant::delete_publisher"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } +} diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp new file mode 100644 index 0000000..a525b84 --- /dev/null +++ b/realtime/dds_lms.cpp @@ -0,0 +1,140 @@ +#include + +#include "ccpp_dds_dcps.h" +#include "check_status.h" + +#include "ccpp_LargeMsg.h" + +bool running = true; + +static void catch_function(int signo) { + running = false; + std::cout << "Catching Ctrl-C, shutting down..." << std::endl; +} + +int main(int argc, char *argv[]) +{ + /* Register a signal handler so DDS doesn't just sit there... */ + if (signal(SIGINT, catch_function) == SIG_ERR) + { + fputs("An error occurred while setting a signal handler.\n", stderr); + return EXIT_FAILURE; + } + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + DDS::DomainParticipant_var participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + DDS::ReturnCode_t status; + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + char * large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Subscribers's QoS */ + DDS::SubscriberQos sub_qos; + status = participant->get_default_subscriber_qos(sub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); + sub_qos.partition.name.length(1); + sub_qos.partition.name[0] = partition_name; + + /* Create the subscriber */ + DDS::Subscriber_var subscriber = participant->create_subscriber( + sub_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); + + /* Create the Topic */ + DDS::Topic_var large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic specific DataReader */ + DDS::DataReader_var topic_reader = subscriber->create_datareader( + large_message_topic.in(), + DATAREADER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); + + /* Narrow topic_reader down to LargeMessage specific DataReader */ + LargeMsg::LargeMessageDataReader_var data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); + checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); + + LargeMsg::LargeMessageSeq_var large_msg_seq = new LargeMsg::LargeMessageSeq(); + DDS::SampleInfoSeq_var sample_info_seq = new DDS::SampleInfoSeq(); + + std::cout << "Polling DataReader..." << std::endl; + while (running) + { + status = data_reader->take( + large_msg_seq, + sample_info_seq, + DDS::LENGTH_UNLIMITED, + DDS::ANY_SAMPLE_STATE, + DDS::ANY_VIEW_STATE, + DDS::ALIVE_INSTANCE_STATE + ); + checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); + + for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) + { + LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); + std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + } + + status = data_reader->return_loan(large_msg_seq, sample_info_seq); + checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); + + /* Sleep for some amount of time, as not to consume too much CPU cycles. */ +#if defined _WIN32 + Sleep(100); +#else + usleep(100000); +#endif + } + + /* Shutdown */ + { + status = participant->delete_subscriber(subscriber.in()); + checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } +} diff --git a/realtime/idl/LargeMsg.idl b/realtime/idl/LargeMsg.idl new file mode 100644 index 0000000..89ece6e --- /dev/null +++ b/realtime/idl/LargeMsg.idl @@ -0,0 +1,7 @@ +module LargeMsg { + struct LargeMessage { + long seq; // Message sequence number + string content; // message body + }; +#pragma keylist LargeMessage seq +}; diff --git a/realtime/msg/LargeMessage.msg b/realtime/msg/LargeMessage.msg new file mode 100644 index 0000000..0c8dfe0 --- /dev/null +++ b/realtime/msg/LargeMessage.msg @@ -0,0 +1,2 @@ +int64 seq +string content From 367a25d5787f532b06e05d1c75aad26bd5e8d701 Mon Sep 17 00:00:00 2001 From: Jackie Date: Thu, 25 Jun 2015 18:50:27 -0700 Subject: [PATCH 02/34] Improved examples --- realtime/dds_intraproc.cpp | 47 ++++++++++++++++++++++++-------------- realtime/dds_lmp.cpp | 44 +++++++++++++++++++++++++---------- realtime/dds_lms.cpp | 8 +++++-- 3 files changed, 68 insertions(+), 31 deletions(-) diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index d42dcbc..ef96ab7 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -117,28 +117,36 @@ void *publisher_thread(void *unused) checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); /* Send some large messages */ - std::cout << "Sending LargeMessage's" << std::endl; - LargeMsg::LargeMessage * msg; - msg = new LargeMsg::LargeMessage(); - msg->content = std::string(pow(2, 20), '.').c_str(); // ~8.39 million characters struct timespec t; t.tv_sec = 0; - t.tv_nsec = 1000000; - for (int i = 0; i < 290; ++i) - { - checkHandle(msg, "new LargeMsg::LargeMessage"); - - msg->seq = i; + t.tv_nsec = 10000000; + + LargeMsg::LargeMessage msg_buffer[8]; + //msg = new LargeMsg::LargeMessage(); + for (int i = 0; i < 6; i++) + { + int scale = 2*i+16; + // is this line dynamically allocating memory for me? Possibly + msg_buffer[i].content = std::string(pow(2, scale), '.').c_str(); // ~8.39 million characters + } + LargeMsg::LargeMessage msg; + std::cout << "Sending LargeMessage's" << std::endl; - DDS::InstanceHandle_t instance_handle = data_writer->register_instance(*msg); + for (int j = 0; j < 8; ++j) + { + for (int i = 0; i < 100; ++i) + { + checkHandle(&msg, "new LargeMsg::LargeMessage"); - status = data_writer->write(*msg, instance_handle); - checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + msg.seq = i; + msg.content = msg_buffer[j].content; - clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); + DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); + checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); + } } - delete msg; std::cout << "Finished" << std::endl; @@ -146,6 +154,11 @@ void *publisher_thread(void *unused) /* Shutdown */ { + for (int i = 0; i < 8; ++i) + { + DDS::string_free(msg_buffer[i].content); + } + status = publisher->delete_datawriter(data_writer.in()); checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); @@ -249,7 +262,7 @@ void *subscriber_thread(void *unused) struct timespec t; t.tv_sec = 0; - t.tv_nsec = 1000000; + t.tv_nsec = 10000000; std::cout << "Polling DataReader..." << std::endl; while (running) { @@ -266,7 +279,7 @@ void *subscriber_thread(void *unused) for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) { LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); - std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + //std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; } status = data_reader->return_loan(large_msg_seq, sample_info_seq); diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index dbcef7c..bfd586c 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -1,3 +1,5 @@ +#include + #include "ccpp_dds_dcps.h" #include "check_status.h" @@ -73,25 +75,38 @@ int main(int argc, char *argv[]) checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); /* Send some large messages */ - std::cout << "Sending LargeMessage's" << std::endl; - LargeMsg::LargeMessage * msg; - msg = new LargeMsg::LargeMessage(); - msg->content = std::string(pow(2, 20), '.').c_str(); // ~8.39 million characters - for (int i = 0; i < 290; ++i) + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 10000000; + + LargeMsg::LargeMessage msg_buffer[8]; + //msg = new LargeMsg::LargeMessage(); + for (int i = 0; i < 6; i++) { - checkHandle(msg, "new LargeMsg::LargeMessage"); + int scale = 2*i+16; + // is this line dynamically allocating memory for me? Possibly + msg_buffer[i].content = std::string(pow(2, scale), '.').c_str(); // ~8.39 million characters + } + LargeMsg::LargeMessage msg; + std::cout << "Sending LargeMessage's" << std::endl; - msg->seq = i; + for (int j = 0; j < 8; ++j) + { + for (int i = 0; i < 100; ++i) + { + checkHandle(&msg, "new LargeMsg::LargeMessage"); - DDS::InstanceHandle_t instance_handle = data_writer->register_instance(*msg); + msg.seq = i; + msg.content = msg_buffer[j].content; - status = data_writer->write(*msg, instance_handle); - checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); - usleep(100000); + status = data_writer->write(msg, instance_handle); + checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); + } } - delete msg; std::cout << "Finished" << std::endl; @@ -99,6 +114,11 @@ int main(int argc, char *argv[]) /* Shutdown */ { + for (int i = 0; i < 8; ++i) + { + DDS::string_free(msg_buffer[i].content); + } + status = publisher->delete_datawriter(data_writer.in()); checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index a525b84..c183606 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -94,6 +94,10 @@ int main(int argc, char *argv[]) LargeMsg::LargeMessageSeq_var large_msg_seq = new LargeMsg::LargeMessageSeq(); DDS::SampleInfoSeq_var sample_info_seq = new DDS::SampleInfoSeq(); + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 10000000; + std::cout << "Polling DataReader..." << std::endl; while (running) { @@ -110,7 +114,7 @@ int main(int argc, char *argv[]) for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) { LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); - std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + //std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; } status = data_reader->return_loan(large_msg_seq, sample_info_seq); @@ -120,7 +124,7 @@ int main(int argc, char *argv[]) #if defined _WIN32 Sleep(100); #else - usleep(100000); + clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); #endif } From a94522e70fe1ebd1813930a34cafb2ea6a1cccec Mon Sep 17 00:00:00 2001 From: Jackie Date: Fri, 26 Jun 2015 13:36:07 -0700 Subject: [PATCH 03/34] Examples correspond to ROS examples --- realtime/CMakeLists.txt | 3 ++- realtime/dds_intraproc.cpp | 49 ++++++++++++++++---------------------- realtime/dds_lmp.cpp | 7 +++--- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt index 7698325..fa915a4 100644 --- a/realtime/CMakeLists.txt +++ b/realtime/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(large_message_cpp) +project(realtime) +set (CMAKE_CXX_FLAGS "-std=c++11") find_package(opensplice REQUIRED) include_directories(${OPENSPLICE_INCLUDE_DIRS}) diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index ef96ab7..52db586 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "ccpp_dds_dcps.h" #include "check_status.h" @@ -47,7 +48,7 @@ static void start_rt_thread(void *(*f)(void*)) void *publisher_thread(void *unused) { - setprio(80, SCHED_RR); + //setprio(80, SCHED_RR); DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; const char * partition_name = "Default"; const char * topic_name = "big_chatter"; @@ -121,27 +122,29 @@ void *publisher_thread(void *unused) t.tv_sec = 0; t.tv_nsec = 10000000; - LargeMsg::LargeMessage msg_buffer[8]; - //msg = new LargeMsg::LargeMessage(); - for (int i = 0; i < 6; i++) + const int buffer_size = 6; + std::shared_ptr msg_buffer[buffer_size]; + //LargeMsg::LargeMessage msg_buffer[buffer_size]; + + for (int i = 0; i < buffer_size; i++) { int scale = 2*i+16; // is this line dynamically allocating memory for me? Possibly - msg_buffer[i].content = std::string(pow(2, scale), '.').c_str(); // ~8.39 million characters + LargeMsg::LargeMessage msg; + msg.content = std::string(pow(2, scale), '.').c_str(); // ~8.39 million characters + msg_buffer[i] = std::make_shared(msg); } - LargeMsg::LargeMessage msg; std::cout << "Sending LargeMessage's" << std::endl; - for (int j = 0; j < 8; ++j) + for (int j = 0; j < buffer_size; ++j) { for (int i = 0; i < 100; ++i) { - checkHandle(&msg, "new LargeMsg::LargeMessage"); + checkHandle(msg_buffer[j].get(), "new LargeMsg::LargeMessage"); - msg.seq = i; - msg.content = msg_buffer[j].content; + msg_buffer[j]->seq = i; - DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); + DDS::InstanceHandle_t instance_handle = data_writer->register_instance(*msg_buffer[j]); checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); @@ -156,7 +159,7 @@ void *publisher_thread(void *unused) { for (int i = 0; i < 8; ++i) { - DDS::string_free(msg_buffer[i].content); + DDS::string_free(msg_buffer[i]->content); } status = publisher->delete_datawriter(data_writer.in()); @@ -178,7 +181,7 @@ void *publisher_thread(void *unused) void *subscriber_thread(void *unused) { - setprio(80, SCHED_RR); + //setprio(80, SCHED_RR); /* Register a signal handler so DDS doesn't just sit there... */ if (signal(SIGINT, catch_function) == SIG_ERR) { @@ -276,11 +279,13 @@ void *subscriber_thread(void *unused) ); checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); + /* for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) { LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); - //std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; } + */ status = data_reader->return_loan(large_msg_seq, sample_info_seq); checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); @@ -313,21 +318,7 @@ int main(int argc, char *argv[]) { struct timespec t; - setprio(80, SCHED_RR); - start_rt_thread(&subscriber_thread); - start_rt_thread(&publisher_thread); - - // Set priority for the main thread (monitor) - setprio(60, SCHED_RR); - t.tv_sec = 0; - t.tv_nsec = 500000; - - // Main thread polls at a regular interval - while (1) - { - // Sleep for 500 ms - clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); - } + publisher_thread(NULL); } diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index bfd586c..30ccab3 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -79,9 +79,10 @@ int main(int argc, char *argv[]) t.tv_sec = 0; t.tv_nsec = 10000000; - LargeMsg::LargeMessage msg_buffer[8]; + const int buffer_size = 6; + LargeMsg::LargeMessage msg_buffer[buffer_size]; //msg = new LargeMsg::LargeMessage(); - for (int i = 0; i < 6; i++) + for (int i = 0; i < buffer_size; i++) { int scale = 2*i+16; // is this line dynamically allocating memory for me? Possibly @@ -90,7 +91,7 @@ int main(int argc, char *argv[]) LargeMsg::LargeMessage msg; std::cout << "Sending LargeMessage's" << std::endl; - for (int j = 0; j < 8; ++j) + for (int j = 0; j < buffer_size; ++j) { for (int i = 0; i < 100; ++i) { From 9d386d7bd98a5b4fefe4998c0d153538189d09cd Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 1 Jul 2015 15:07:28 -0700 Subject: [PATCH 04/34] Incorporate rttest with dds large message examples --- realtime/CMakeLists.txt | 16 +- realtime/dds_intraproc.cpp | 303 ++++--------------------------------- realtime/dds_lmp.cpp | 140 ++--------------- realtime/dds_lms.cpp | 144 ++---------------- 4 files changed, 67 insertions(+), 536 deletions(-) diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt index fa915a4..8b50643 100644 --- a/realtime/CMakeLists.txt +++ b/realtime/CMakeLists.txt @@ -2,21 +2,29 @@ cmake_minimum_required(VERSION 2.8) project(realtime) set (CMAKE_CXX_FLAGS "-std=c++11") +find_package(rttest REQUIRED) + +#include(ExamplePublisher.hpp ExampleSubscriber.hpp) + + +include_directories(${rttest_INCLUDE_DIRS}) + + find_package(opensplice REQUIRED) include_directories(${OPENSPLICE_INCLUDE_DIRS}) ospl_add_idl(idl/LargeMsg.idl) add_executable(dds_lms dds_lms.cpp) -target_link_libraries(dds_lms ${OPENSPLICE_LIBRARIES}) +target_link_libraries(dds_lms ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) add_executable(dds_lmp dds_lmp.cpp) -target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES}) +target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) find_package(Threads) if(NOT Threads_FOUND) - message(WARNING "Pthread not found. Real-time intra-process pub/sub example will not be built.") + message(WARNING "pthread not found. Real-time intra-process pub/sub example will not be built.") elseif(Threads_FOUND) add_executable(dds_intraproc dds_intraproc.cpp) - target_link_libraries(dds_intraproc ${OPENSPLICE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(dds_intraproc ${OPENSPLICE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${rttest_LIBRARIES}) endif() diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index 52db586..5628dae 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -2,26 +2,13 @@ #include #include -#include "ccpp_dds_dcps.h" -#include "check_status.h" -#include "ccpp_LargeMsg.h" +#include +#include "ExampleSubscriber.hpp" +#include "ExamplePublisher.hpp" -bool running = true; - -static void catch_function(int signo) { - running = false; - std::cout << "Catching Ctrl-C, shutting down..." << std::endl; -} - -static void setprio(int prio, int sched) -{ - struct sched_param param; - // Set realtime priority for this thread - param.sched_priority = prio; - if (sched_setscheduler(0, sched, ¶m) < 0) - perror("sched_setscheduler"); -} +ExamplePublisher pub; +ExampleSubscriber sub; static void start_rt_thread(void *(*f)(void*)) { @@ -36,6 +23,7 @@ static void start_rt_thread(void *(*f)(void*)) } /* Set the requested stacksize for this thread */ + // put this in rttest /*if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + MAX_SAFE_STACK)) { fprintf(stderr, "Couldn't set requested stack size for pthread"); @@ -46,279 +34,46 @@ static void start_rt_thread(void *(*f)(void*)) pthread_create(&thread, &attr, f, NULL); } -void *publisher_thread(void *unused) +void* pub_callback(void * unused) { - //setprio(80, SCHED_RR); - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; - - /* Create Domain Participant Factory */ - DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); - checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); - - /* Create Domain Participant */ - std::cout << "Creating domain participant in publisher" << std::endl; - DDS::DomainParticipant_var participant = dpf->create_participant( - domain, - PARTICIPANT_QOS_DEFAULT, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); - - DDS::ReturnCode_t status; - - /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; - status = participant->get_default_topic_qos(default_topic_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); - // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; - - /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); - checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - char * large_message_type_name = large_message_ts->get_type_name(); - status = large_message_ts->register_type(participant.in(), large_message_type_name); - checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); - - /* Setup the Publisher's QoS */ - DDS::PublisherQos pub_qos; - status = participant->get_default_publisher_qos(pub_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); - pub_qos.partition.name.length(1); - pub_qos.partition.name[0] = partition_name; - - /* Create the publisher */ - DDS::Publisher_var publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); - checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); - - /* Create the Topic */ - DDS::Topic_var large_message_topic = participant->create_topic( - topic_name, - large_message_type_name, - default_topic_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); - - /* Create Topic DataWriter */ - DDS::DataWriter_var topic_writer = publisher->create_datawriter( - large_message_topic.in(), - DATAWRITER_QOS_USE_TOPIC_QOS, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); - - /* Narrow the Topic DataWriter to be only for LargeMessage */ - LargeMsg::LargeMessageDataWriter_var data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); - checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); - - /* Send some large messages */ - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 10000000; - - const int buffer_size = 6; - std::shared_ptr msg_buffer[buffer_size]; - //LargeMsg::LargeMessage msg_buffer[buffer_size]; - - for (int i = 0; i < buffer_size; i++) - { - int scale = 2*i+16; - // is this line dynamically allocating memory for me? Possibly - LargeMsg::LargeMessage msg; - msg.content = std::string(pow(2, scale), '.').c_str(); // ~8.39 million characters - msg_buffer[i] = std::make_shared(msg); - } - std::cout << "Sending LargeMessage's" << std::endl; - - for (int j = 0; j < buffer_size; ++j) - { - for (int i = 0; i < 100; ++i) - { - checkHandle(msg_buffer[j].get(), "new LargeMsg::LargeMessage"); - - msg_buffer[j]->seq = i; - - DDS::InstanceHandle_t instance_handle = data_writer->register_instance(*msg_buffer[j]); - checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); - - clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); - } - } - - std::cout << "Finished" << std::endl; - - getchar(); - - /* Shutdown */ - { - for (int i = 0; i < 8; ++i) - { - DDS::string_free(msg_buffer[i]->content); - } - - status = publisher->delete_datawriter(data_writer.in()); - checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + pub.callback(); +} - status = participant->delete_publisher(publisher.in()); - checkStatus(status, "DDS::DomainParticipant::delete_publisher"); +void* sub_callback(void * unused) +{ + sub.callback(); +} - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); +void *publisher_thread(void *unused) +{ + pub.init(); - DDS::string_free(large_message_type_name); + rttest_spin(pub_callback, NULL); - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); - } - return NULL; + rttest_write_results(); + pub.teardown(); } void *subscriber_thread(void *unused) { - //setprio(80, SCHED_RR); - /* Register a signal handler so DDS doesn't just sit there... */ - if (signal(SIGINT, catch_function) == SIG_ERR) - { - fputs("An error occurred while setting a signal handler.\n", stderr); - return NULL; - } - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; - - /* Create Domain Participant Factory */ - DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); - checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); - - /* Create Domain Participant */ - std::cout << "Creating domain participant in subscriber" << std::endl; - DDS::DomainParticipant_var participant = dpf->create_participant( - domain, - PARTICIPANT_QOS_DEFAULT, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); - - DDS::ReturnCode_t status; - - /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; - status = participant->get_default_topic_qos(default_topic_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); - // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; - - /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); - checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - char * large_message_type_name = large_message_ts->get_type_name(); - status = large_message_ts->register_type(participant.in(), large_message_type_name); - checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); - - /* Setup the Subscribers's QoS */ - DDS::SubscriberQos sub_qos; - status = participant->get_default_subscriber_qos(sub_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); - sub_qos.partition.name.length(1); - sub_qos.partition.name[0] = partition_name; + sub.init(); - /* Create the subscriber */ - DDS::Subscriber_var subscriber = participant->create_subscriber( - sub_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); + rttest_init_new_thread(); + rttest_set_sched_priority(90, SCHED_RR); - /* Create the Topic */ - DDS::Topic_var large_message_topic = participant->create_topic( - topic_name, - large_message_type_name, - default_topic_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + rttest_spin(sub_callback, NULL); - /* Create Topic specific DataReader */ - DDS::DataReader_var topic_reader = subscriber->create_datareader( - large_message_topic.in(), - DATAREADER_QOS_USE_TOPIC_QOS, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); + rttest_write_results_file("rttest_subscriber_results"); + rttest_finish(); - /* Narrow topic_reader down to LargeMessage specific DataReader */ - LargeMsg::LargeMessageDataReader_var data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); - checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); - - LargeMsg::LargeMessageSeq_var large_msg_seq = new LargeMsg::LargeMessageSeq(); - DDS::SampleInfoSeq_var sample_info_seq = new DDS::SampleInfoSeq(); - - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 10000000; - std::cout << "Polling DataReader..." << std::endl; - while (running) - { - status = data_reader->take( - large_msg_seq, - sample_info_seq, - DDS::LENGTH_UNLIMITED, - DDS::ANY_SAMPLE_STATE, - DDS::ANY_VIEW_STATE, - DDS::ALIVE_INSTANCE_STATE - ); - checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); - - /* - for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) - { - LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); - std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; - } - */ - - status = data_reader->return_loan(large_msg_seq, sample_info_seq); - checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); - - /* Sleep for some amount of time, as not to consume too much CPU cycles. */ -#if defined _WIN32 - Sleep(100); -#else - clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); -#endif - } - - /* Shutdown */ - { - status = participant->delete_subscriber(subscriber.in()); - checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); - - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); - - DDS::string_free(large_message_type_name); - - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); - } - return NULL; + sub.teardown(); } int main(int argc, char *argv[]) { - struct timespec t; - + rttest_read_args(argc, argv); start_rt_thread(&subscriber_thread); - publisher_thread(NULL); + + rttest_finish(); } diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index 30ccab3..dc19a30 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -1,137 +1,25 @@ #include -#include "ccpp_dds_dcps.h" -#include "check_status.h" +#include +#include "ExamplePublisher.hpp" -#include "ccpp_LargeMsg.h" +ExamplePublisher pub; -int main(int argc, char *argv[]) +void* pub_callback(void * unused) { - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; - - /* Create Domain Participant Factory */ - DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); - checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); - - /* Create Domain Participant */ - DDS::DomainParticipant_var participant = dpf->create_participant( - domain, - PARTICIPANT_QOS_DEFAULT, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); - - DDS::ReturnCode_t status; - - /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; - status = participant->get_default_topic_qos(default_topic_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); - // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; - - /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); - checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - char * large_message_type_name = large_message_ts->get_type_name(); - status = large_message_ts->register_type(participant.in(), large_message_type_name); - checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); - - /* Setup the Publisher's QoS */ - DDS::PublisherQos pub_qos; - status = participant->get_default_publisher_qos(pub_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); - pub_qos.partition.name.length(1); - pub_qos.partition.name[0] = partition_name; - - /* Create the publisher */ - DDS::Publisher_var publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); - checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); - - /* Create the Topic */ - DDS::Topic_var large_message_topic = participant->create_topic( - topic_name, - large_message_type_name, - default_topic_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); - - /* Create Topic DataWriter */ - DDS::DataWriter_var topic_writer = publisher->create_datawriter( - large_message_topic.in(), - DATAWRITER_QOS_USE_TOPIC_QOS, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); - - /* Narrow the Topic DataWriter to be only for LargeMessage */ - LargeMsg::LargeMessageDataWriter_var data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); - checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); - - /* Send some large messages */ - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 10000000; - - const int buffer_size = 6; - LargeMsg::LargeMessage msg_buffer[buffer_size]; - //msg = new LargeMsg::LargeMessage(); - for (int i = 0; i < buffer_size; i++) - { - int scale = 2*i+16; - // is this line dynamically allocating memory for me? Possibly - msg_buffer[i].content = std::string(pow(2, scale), '.').c_str(); // ~8.39 million characters - } - LargeMsg::LargeMessage msg; - std::cout << "Sending LargeMessage's" << std::endl; - - for (int j = 0; j < buffer_size; ++j) - { - for (int i = 0; i < 100; ++i) - { - checkHandle(&msg, "new LargeMsg::LargeMessage"); - - msg.seq = i; - msg.content = msg_buffer[j].content; - - DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); - - status = data_writer->write(msg, instance_handle); - checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); - - clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); - } - } - - std::cout << "Finished" << std::endl; - - getchar(); - - /* Shutdown */ - { - for (int i = 0; i < 8; ++i) - { - DDS::string_free(msg_buffer[i].content); - } + pub.callback(); +} - status = publisher->delete_datawriter(data_writer.in()); - checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); +int main(int argc, char *argv[]) +{ + pub.init(); - status = participant->delete_publisher(publisher.in()); - checkStatus(status, "DDS::DomainParticipant::delete_publisher"); + rttest_read_args(argc, argv); - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + rttest_spin(pub_callback, NULL); - DDS::string_free(large_message_type_name); + rttest_write_results(); + rttest_finish(); - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); - } + pub.teardown(); } diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index c183606..9e728b1 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -1,144 +1,24 @@ #include -#include "ccpp_dds_dcps.h" -#include "check_status.h" +#include +#include "ExampleSubscriber.hpp" -#include "ccpp_LargeMsg.h" +ExampleSubscriber sub; -bool running = true; - -static void catch_function(int signo) { - running = false; - std::cout << "Catching Ctrl-C, shutting down..." << std::endl; +void* sub_callback(void * unused) +{ + sub.callback(); } int main(int argc, char *argv[]) { - /* Register a signal handler so DDS doesn't just sit there... */ - if (signal(SIGINT, catch_function) == SIG_ERR) - { - fputs("An error occurred while setting a signal handler.\n", stderr); - return EXIT_FAILURE; - } - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; - - /* Create Domain Participant Factory */ - DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::get_instance(); - checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); - - /* Create Domain Participant */ - DDS::DomainParticipant_var participant = dpf->create_participant( - domain, - PARTICIPANT_QOS_DEFAULT, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); - - DDS::ReturnCode_t status; - - /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; - status = participant->get_default_topic_qos(default_topic_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); - // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; - - /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); - checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - char * large_message_type_name = large_message_ts->get_type_name(); - status = large_message_ts->register_type(participant.in(), large_message_type_name); - checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); - - /* Setup the Subscribers's QoS */ - DDS::SubscriberQos sub_qos; - status = participant->get_default_subscriber_qos(sub_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); - sub_qos.partition.name.length(1); - sub_qos.partition.name[0] = partition_name; - - /* Create the subscriber */ - DDS::Subscriber_var subscriber = participant->create_subscriber( - sub_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); - - /* Create the Topic */ - DDS::Topic_var large_message_topic = participant->create_topic( - topic_name, - large_message_type_name, - default_topic_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); - - /* Create Topic specific DataReader */ - DDS::DataReader_var topic_reader = subscriber->create_datareader( - large_message_topic.in(), - DATAREADER_QOS_USE_TOPIC_QOS, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); - - /* Narrow topic_reader down to LargeMessage specific DataReader */ - LargeMsg::LargeMessageDataReader_var data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); - checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); - - LargeMsg::LargeMessageSeq_var large_msg_seq = new LargeMsg::LargeMessageSeq(); - DDS::SampleInfoSeq_var sample_info_seq = new DDS::SampleInfoSeq(); - - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 10000000; - - std::cout << "Polling DataReader..." << std::endl; - while (running) - { - status = data_reader->take( - large_msg_seq, - sample_info_seq, - DDS::LENGTH_UNLIMITED, - DDS::ANY_SAMPLE_STATE, - DDS::ANY_VIEW_STATE, - DDS::ALIVE_INSTANCE_STATE - ); - checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); - - for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) - { - LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); - //std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; - } - - status = data_reader->return_loan(large_msg_seq, sample_info_seq); - checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); - - /* Sleep for some amount of time, as not to consume too much CPU cycles. */ -#if defined _WIN32 - Sleep(100); -#else - clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL); -#endif - } - - /* Shutdown */ - { - status = participant->delete_subscriber(subscriber.in()); - checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + sub.init(); - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + rttest_read_args(argc, argv); + rttest_spin(sub_callback, NULL); - DDS::string_free(large_message_type_name); + rttest_write_results(); + rttest_finish(); - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); - } + sub.teardown(); } From 9854b0a2c5ce68379b242c12c3db7e4a6a21b6de Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 1 Jul 2015 15:08:03 -0700 Subject: [PATCH 05/34] Add dds classes --- realtime/ExamplePublisher.hpp | 142 ++++++++++++++++++++++++++++++++ realtime/ExampleSubscriber.hpp | 146 +++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 realtime/ExamplePublisher.hpp create mode 100644 realtime/ExampleSubscriber.hpp diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp new file mode 100644 index 0000000..4625bd4 --- /dev/null +++ b/realtime/ExamplePublisher.hpp @@ -0,0 +1,142 @@ +#include "ccpp_dds_dcps.h" +#include "check_status.h" + +#include "ccpp_LargeMsg.h" + +class ExamplePublisher +{ + private: + LargeMsg::LargeMessageDataWriter_var data_writer; + DDS::Publisher_var publisher; + DDS::DomainParticipantFactory_var dpf; + DDS::DomainParticipant_var participant; + DDS::Topic_var large_message_topic; + char * large_message_type_name; + LargeMsg::LargeMessage msg; + DDS::ReturnCode_t status; + int i; + + public: + void callback(); + bool init(); + bool teardown(); +}; + +bool ExamplePublisher::init() +{ + this->i = 0; + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + this->dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + std::cout << "Creating domain participant in publisher" << std::endl; + this->participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + this->large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Publisher's QoS */ + DDS::PublisherQos pub_qos; + status = participant->get_default_publisher_qos(pub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); + pub_qos.partition.name.length(1); + pub_qos.partition.name[0] = partition_name; + + /* Create the publisher */ + this->publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); + checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); + + /* Create the Topic */ + this->large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic DataWriter */ + DDS::DataWriter_var topic_writer = publisher->create_datawriter( + large_message_topic.in(), + DATAWRITER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); + + /* Narrow the Topic DataWriter to be only for LargeMessage */ + this->data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); + checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); + + /* Send some large messages */ + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 10000000; + + + this->msg.content = std::string(pow(2, 24), '.').c_str(); + + std::cout << "Ready to send LargeMessage's" << std::endl; + return true; +} + +void ExamplePublisher::callback() +{ + checkHandle(&msg, "new LargeMsg::LargeMessage"); + + msg.seq = i; + i++; + + DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); + checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); +} + + +bool ExamplePublisher::teardown() +{ + std::cout << "Finished" << std::endl; + getchar(); + /* Shutdown */ + { + DDS::string_free(msg.content); + + status = publisher->delete_datawriter(data_writer.in()); + checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + + status = participant->delete_publisher(publisher.in()); + checkStatus(status, "DDS::DomainParticipant::delete_publisher"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } + return true; +} diff --git a/realtime/ExampleSubscriber.hpp b/realtime/ExampleSubscriber.hpp new file mode 100644 index 0000000..1744d37 --- /dev/null +++ b/realtime/ExampleSubscriber.hpp @@ -0,0 +1,146 @@ +#include "ccpp_dds_dcps.h" +#include "check_status.h" + +#include "ccpp_LargeMsg.h" + +class ExampleSubscriber +{ + private: + DDS::DomainParticipantFactory_var dpf; + DDS::DomainParticipant_var participant; + DDS::Subscriber_var subscriber; + LargeMsg::LargeMessageDataReader_var data_reader; + DDS::Topic_var large_message_topic; + char * large_message_type_name; + LargeMsg::LargeMessageSeq_var large_msg_seq; + DDS::SampleInfoSeq_var sample_info_seq; + bool subscriber_running; + DDS::ReturnCode_t status; + + public: + void callback(); + bool init(); + bool teardown(); +}; + + +bool ExampleSubscriber::init() +{ + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + this->dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + std::cout << "Creating domain participant in subscriber" << std::endl; + this->participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + this->large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Subscribers's QoS */ + DDS::SubscriberQos sub_qos; + status = participant->get_default_subscriber_qos(sub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); + sub_qos.partition.name.length(1); + sub_qos.partition.name[0] = partition_name; + + /* Create the subscriber */ + this->subscriber = participant->create_subscriber( + sub_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); + + /* Create the Topic */ + this->large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic specific DataReader */ + DDS::DataReader_var topic_reader = subscriber->create_datareader( + large_message_topic.in(), + DATAREADER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); + + /* Narrow topic_reader down to LargeMessage specific DataReader */ + this->data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); + checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); + + this->large_msg_seq = new LargeMsg::LargeMessageSeq(); + this->sample_info_seq = new DDS::SampleInfoSeq(); + + std::cout << "Polling DataReader..." << std::endl; + return true; +} + +void ExampleSubscriber::callback() +{ + status = data_reader->take( + large_msg_seq, + sample_info_seq, + DDS::LENGTH_UNLIMITED, + DDS::ANY_SAMPLE_STATE, + DDS::ANY_VIEW_STATE, + DDS::ALIVE_INSTANCE_STATE + ); + checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); + + /* + for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) + { + LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); + std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + } + */ + + status = data_reader->return_loan(large_msg_seq, sample_info_seq); + checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); +} + +bool ExampleSubscriber::teardown() +{ + /* Shutdown */ + status = participant->delete_subscriber(subscriber.in()); + checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + return true; +} + From 9b858324d1486ca36f005f552435090d73b148de Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 1 Jul 2015 15:45:28 -0700 Subject: [PATCH 06/34] dds C++ publisher is not realtime safe --- realtime/ExampleSubscriber.hpp | 7 ++++--- realtime/dds_intraproc.cpp | 8 +++----- realtime/dds_lmp.cpp | 5 +++++ realtime/dds_lms.cpp | 2 ++ 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/realtime/ExampleSubscriber.hpp b/realtime/ExampleSubscriber.hpp index 1744d37..d455e0a 100644 --- a/realtime/ExampleSubscriber.hpp +++ b/realtime/ExampleSubscriber.hpp @@ -130,17 +130,18 @@ void ExampleSubscriber::callback() bool ExampleSubscriber::teardown() { + // TODO investigate why preconditions not met /* Shutdown */ status = participant->delete_subscriber(subscriber.in()); - checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + //checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + //checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); DDS::string_free(large_message_type_name); status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + //checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); return true; } diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index 5628dae..c2e6faf 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -50,8 +50,9 @@ void *publisher_thread(void *unused) rttest_spin(pub_callback, NULL); - rttest_write_results(); + rttest_write_results_file("rttest_publisher_results"); pub.teardown(); + rttest_finish(); } void *subscriber_thread(void *unused) @@ -64,9 +65,8 @@ void *subscriber_thread(void *unused) rttest_spin(sub_callback, NULL); rttest_write_results_file("rttest_subscriber_results"); - rttest_finish(); - sub.teardown(); + rttest_finish(); } int main(int argc, char *argv[]) @@ -74,6 +74,4 @@ int main(int argc, char *argv[]) rttest_read_args(argc, argv); start_rt_thread(&subscriber_thread); publisher_thread(NULL); - - rttest_finish(); } diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index dc19a30..27a9bcd 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -3,6 +3,8 @@ #include #include "ExamplePublisher.hpp" +#define STACK_SIZE 1024*1024 + ExamplePublisher pub; void* pub_callback(void * unused) @@ -15,6 +17,9 @@ int main(int argc, char *argv[]) pub.init(); rttest_read_args(argc, argv); + rttest_set_sched_priority(90, SCHED_RR); + rttest_lock_memory(); + rttest_prefault_stack_size(STACK_SIZE); rttest_spin(pub_callback, NULL); diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index 9e728b1..4187b09 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -15,6 +15,8 @@ int main(int argc, char *argv[]) sub.init(); rttest_read_args(argc, argv); + rttest_set_sched_priority(90, SCHED_RR); + rttest_spin(sub_callback, NULL); rttest_write_results(); From 5ca58cb81f96e8e036b6b616d7409f926ede7b3e Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 1 Jul 2015 16:28:39 -0700 Subject: [PATCH 07/34] fail to prevent pagefaults in publisher --- realtime/ExamplePublisher.hpp | 8 ++------ realtime/dds_lmp.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp index 4625bd4..4577439 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/ExamplePublisher.hpp @@ -92,11 +92,6 @@ bool ExamplePublisher::init() this->data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); - /* Send some large messages */ - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 10000000; - this->msg.content = std::string(pow(2, 24), '.').c_str(); @@ -112,7 +107,8 @@ void ExamplePublisher::callback() i++; DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); - checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + status = data_writer->write(msg, instance_handle); + //checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); } diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index 27a9bcd..498bd59 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -3,7 +3,7 @@ #include #include "ExamplePublisher.hpp" -#define STACK_SIZE 1024*1024 +#define STACK_SIZE 1024*1024*1024 ExamplePublisher pub; @@ -18,8 +18,9 @@ int main(int argc, char *argv[]) rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); - rttest_lock_memory(); - rttest_prefault_stack_size(STACK_SIZE); + //rttest_lock_memory(); + //rttest_prefault_stack_size(STACK_SIZE); + rttest_lock_and_prefault_dynamic(STACK_SIZE); rttest_spin(pub_callback, NULL); From 1aeb1918e154cc69d181576fc9343b7797b4ab82 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 1 Jul 2015 16:54:49 -0700 Subject: [PATCH 08/34] Fix publisher, maybe, fill in C publisher --- realtime/CMakeLists.txt | 2 +- realtime/ExamplePublisher.hpp | 3 +- tutorial_c/publisher/CMakeLists.txt | 9 +++-- tutorial_c/publisher/build.sh | 2 +- tutorial_c/publisher/main.c | 51 ++++++++++++++++++++++++++++- 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt index 8b50643..3b51fca 100644 --- a/realtime/CMakeLists.txt +++ b/realtime/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(rttest REQUIRED) #include(ExamplePublisher.hpp ExampleSubscriber.hpp) - +link_directories(${rttest_LIBRARY_DIR}) include_directories(${rttest_INCLUDE_DIRS}) diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp index 4577439..6a53b9e 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/ExamplePublisher.hpp @@ -14,6 +14,7 @@ class ExamplePublisher char * large_message_type_name; LargeMsg::LargeMessage msg; DDS::ReturnCode_t status; + DDS::InstanceHandle_t instance_handle; int i; public: @@ -94,6 +95,7 @@ bool ExamplePublisher::init() this->msg.content = std::string(pow(2, 24), '.').c_str(); + instance_handle = data_writer->register_instance(msg); std::cout << "Ready to send LargeMessage's" << std::endl; return true; @@ -106,7 +108,6 @@ void ExamplePublisher::callback() msg.seq = i; i++; - DDS::InstanceHandle_t instance_handle = data_writer->register_instance(msg); status = data_writer->write(msg, instance_handle); //checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); } diff --git a/tutorial_c/publisher/CMakeLists.txt b/tutorial_c/publisher/CMakeLists.txt index 5324fe6..d0caeca 100644 --- a/tutorial_c/publisher/CMakeLists.txt +++ b/tutorial_c/publisher/CMakeLists.txt @@ -1,10 +1,13 @@ cmake_minimum_required(VERSION 2.8) project(publisher) +find_package(rttest REQUIRED) + find_package(opensplice REQUIRED) + # find_package only exposes the c++ include directories but not the c headers -include_directories(c /usr/include/opensplice/dcps/C/SAC ${OPENSPLICE_INCLUDE_DIRS}) -link_directories(${OPENSPLICE_LIBRARY_DIRS}) +include_directories(c /usr/include/opensplice/dcps/C/SAC ${OPENSPLICE_INCLUDE_DIRS} ${rttest_INCLUDE_DIRS}) +link_directories(${OPENSPLICE_LIBRARY_DIRS} ${rttest_LIBRARY_DIR}) add_executable(publisher main.c c/ChatSacDcps.c c/ChatSplDcps.c) -target_link_libraries(publisher ${OPENSPLICE_LIBRARIES}) +target_link_libraries(publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) diff --git a/tutorial_c/publisher/build.sh b/tutorial_c/publisher/build.sh index a3b4aec..8ee6e2d 100755 --- a/tutorial_c/publisher/build.sh +++ b/tutorial_c/publisher/build.sh @@ -8,6 +8,6 @@ cd .. rm -fr build mkdir build cd build -cmake .. +cmake .. -DCMAKE_INSTALL_PREFIX=~/local make cd .. diff --git a/tutorial_c/publisher/main.c b/tutorial_c/publisher/main.c index 15506f6..b7235cd 100644 --- a/tutorial_c/publisher/main.c +++ b/tutorial_c/publisher/main.c @@ -3,6 +3,8 @@ #include "Chat.h" #include "unistd.h" +#define MAX_MSG_LEN 128 + int main ( int argc, char *argv[]) @@ -156,7 +158,54 @@ int main ( } printf("Created datawriter (NameService).\n");*/ - sleep(5); + // Initialize message + int ownID = 0; + + Chat_ChatMessage *msg; + msg = Chat_ChatMessage__alloc(); + //checkHandle(msg, "Chat_ChatMessage__alolc"); + msg->userID = ownID; + msg->index = 0; + msg->content = DDS_string_alloc(MAX_MSG_LEN); + //checkHandle(msg->content, "DDS_string_alloc"); + snprintf(msg->content, MAX_MSG_LEN, "hello world"); + + // register a chat message + DDS_InstanceHandle_t userHandle; + userHandle = Chat_ChatMessageDataWriter_register_instance(talker, msg); + + Chat_NameService ns; + ns.userID = ownID; + ns.name = DDS_string_alloc(Chat_MAX_NAME+1); + //checkHandle(ns.name, "DDS_string_alloc"); + char *chatterName; + if (chatterName) { + strncpy(ns.name, chatterName, Chat_MAX_NAME + 1); + } + else { + snprintf(ns.name, Chat_MAX_NAME+1, "Chatter %d", ownID); + } + + // Write user information + status = Chat_NameServiceDataWriter_write(nameServer, &ns, DDS_HANDLE_NIL); + //checkStatus(status, "Chat_ChatMessageDataWriter_write"); + + // Write a message + status = Chat_ChatMessageDataWriter_write(talker, msg, userHandle); + // checkStatus(status, "Chat_ChatMessageDataWriter_write"); + + // pause + sleep(1); + + int i = 0; + for (i = 1; i < 6; ++i) + { + msg->index = i; + snprintf(msg->content, MAX_MSG_LEN, "Message number: %d", msg->index); + status = Chat_ChatMessageDataWriter_write(talker, msg, userHandle); + // checkStatus(status, "Chat_ChatMessageDataWriter_write"); + sleep(1); + } /* Remove the DataWriters */ From c787094f8acea252f444151f1fa10395921a8717 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 1 Jul 2015 17:48:41 -0700 Subject: [PATCH 09/34] C publisher has much better performance! --- tutorial_c/publisher/CMakeLists.txt | 5 ++++- tutorial_c/publisher/main.c | 29 ----------------------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/tutorial_c/publisher/CMakeLists.txt b/tutorial_c/publisher/CMakeLists.txt index d0caeca..c7ea618 100644 --- a/tutorial_c/publisher/CMakeLists.txt +++ b/tutorial_c/publisher/CMakeLists.txt @@ -10,4 +10,7 @@ include_directories(c /usr/include/opensplice/dcps/C/SAC ${OPENSPLICE_INCLUDE_DI link_directories(${OPENSPLICE_LIBRARY_DIRS} ${rttest_LIBRARY_DIR}) add_executable(publisher main.c c/ChatSacDcps.c c/ChatSplDcps.c) -target_link_libraries(publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) +target_link_libraries(publisher ${OPENSPLICE_LIBRARIES}) + +add_executable(rtt_publisher instrumented_main.c c/ChatSacDcps.c c/ChatSplDcps.c) +target_link_libraries(rtt_publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) diff --git a/tutorial_c/publisher/main.c b/tutorial_c/publisher/main.c index b7235cd..aaf0ef3 100644 --- a/tutorial_c/publisher/main.c +++ b/tutorial_c/publisher/main.c @@ -129,35 +129,6 @@ int main ( } printf("Created datawriter.\n"); - /* Create a DataWriter for the NameService Topic - (using the appropriate QoS). */ - /*dw_qos = DDS_DataWriterQos__alloc(); - if (!dw_qos) { - printf("Allocating datawriter QoS failed!!\n"); - exit(-1); - } - status = DDS_Publisher_get_default_datawriter_qos( - chatPublisher, dw_qos); - if (status != DDS_RETCODE_OK) { - printf("Getting default datawriter qos failed!!\n"); - exit(-1); - } - //status = DDS_Publisher_copy_from_topic_qos( - // chatPublisher, dw_qos, setting_topic_qos); - //checkStatus(status, "DDS_Publisher_copy_from_topic_qos"); - dw_qos->writer_data_lifecycle.autodispose_unregistered_instances = FALSE; - nameServer = DDS_Publisher_create_datawriter( - chatPublisher, - nameServiceTopic, - dw_qos, - NULL, - DDS_STATUS_MASK_NONE); - if (!nameServer) { - printf("Creating datawriter (NameService) failed!!\n"); - exit(-1); - } - printf("Created datawriter (NameService).\n");*/ - // Initialize message int ownID = 0; From bf4d52f73d72d3e0312da761e7e61f29a36b2b04 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 1 Jul 2015 17:50:42 -0700 Subject: [PATCH 10/34] add instrumented c publisher --- tutorial_c/publisher/instrumented_main.c | 237 +++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 tutorial_c/publisher/instrumented_main.c diff --git a/tutorial_c/publisher/instrumented_main.c b/tutorial_c/publisher/instrumented_main.c new file mode 100644 index 0000000..f59eb71 --- /dev/null +++ b/tutorial_c/publisher/instrumented_main.c @@ -0,0 +1,237 @@ +/* CreateTopics.c */ +#include "dds_dcps.h" +#include "Chat.h" +#include "unistd.h" + +#include + +#define MAX_MSG_LEN 16777216 + +int i = 0; +Chat_ChatMessageDataWriter talker; +Chat_ChatMessage *msg; +DDS_ReturnCode_t status; +DDS_InstanceHandle_t userHandle; +char *msg_content; + +void* callback(void* unused) +{ + msg->index = i; + snprintf(msg->content, MAX_MSG_LEN, msg_content, msg->index); + status = Chat_ChatMessageDataWriter_write(talker, msg, userHandle); + // checkStatus(status, "Chat_ChatMessageDataWriter_write"); + ++i; +} + +int main ( + int argc, + char *argv[]) +{ + // begin init + + DDS_DomainParticipantFactory dpf; + DDS_DomainParticipant dp; + DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; + Chat_ChatMessageTypeSupport chatMessageTS; + DDS_Topic chatMessageTopic; + char *chatMessageTypeName; + +DDS_PublisherQos *pub_qos; + DDS_DataWriterQos *dw_qos; + DDS_Publisher chatPublisher; + Chat_NameServiceDataWriter nameServer; + char *partitionName = NULL; + + DDS_Topic nameServiceTopic; + + int ownID; + + Chat_NameService ns; + + + /* Create a DomainParticipantFactory and a DomainParticipant */ + /* (using Default QoS settings). */ + dpf = DDS_DomainParticipantFactory_get_instance(); + if (!dpf) { + printf("Creating ParticipantFactory failed!!\n"); + exit(-1); + } + printf("Created ParticipantFactory.\n"); + + dp = DDS_DomainParticipantFactory_create_participant ( + dpf, + domain, + DDS_PARTICIPANT_QOS_DEFAULT, + NULL, + DDS_STATUS_MASK_NONE); + if (!dp) { + printf("Creating Participant failed!!\n"); + exit(-1); + } + printf("Created Participant.\n"); + + + /* Register the required data type for ChatMessage. */ + chatMessageTS = Chat_ChatMessageTypeSupport__alloc(); + if (!chatMessageTS) { + printf ("Allocating TypeSupport failed!!\n"); + exit(-1); + }; + chatMessageTypeName = Chat_ChatMessageTypeSupport_get_type_name(chatMessageTS); + status = Chat_ChatMessageTypeSupport_register_type( + chatMessageTS, dp, chatMessageTypeName); + if (status != DDS_RETCODE_OK) { + printf("Registering data type failed. Status = %d\n", status); + exit(-1); + }; + printf("Registered data type.\n"); + + /*Create the ChatMessage topic */ + chatMessageTopic = DDS_DomainParticipant_create_topic( + dp, + "Chat_ChatMessage", + chatMessageTypeName, + DDS_TOPIC_QOS_DEFAULT, + NULL, + DDS_STATUS_MASK_NONE); + if (!chatMessageTopic) { + printf("Creating ChatMessage topic failed!!\n"); + exit(-1); + }; + printf("Created ChatMessage topic.\n"); + + /* Adapt the default PublisherQos to write into the + "ChatRoom" Partition. */ + partitionName = "ChatRoom"; + pub_qos = DDS_PublisherQos__alloc(); + if (!pub_qos) { + printf("Allocating PublisherQos failed!!\n"); + exit(-1); + } + status = DDS_DomainParticipant_get_default_publisher_qos ( + dp, pub_qos); + if (status != DDS_RETCODE_OK) { + printf("Getting default publisher qos failed!!\n"); + exit(-1); + } + pub_qos->partition.name._length = 1; + pub_qos->partition.name._maximum = 1; + pub_qos->partition.name._buffer = DDS_StringSeq_allocbuf (1); + if (!pub_qos->partition.name._buffer) { + printf("Allocating partition name failed!!\n"); + exit(-1); + } + pub_qos->partition.name._buffer[0] = DDS_string_alloc ( + strlen(partitionName)); + if (!pub_qos->partition.name._buffer[0]) { + printf("Allocating partition name failed!!\n"); + exit(-1); + } + strcpy (pub_qos->partition.name._buffer[0], partitionName); + + /* Create a Publisher for the chatter application. */ + chatPublisher = DDS_DomainParticipant_create_publisher( + dp, pub_qos, NULL, DDS_STATUS_MASK_NONE); + if (!chatPublisher) { + printf("Creating publisher failed!!\n"); + exit(-1); + } + printf("Created publisher.\n"); + + /* Create a DataWriter for the ChatMessage Topic + (using the appropriate QoS). */ + talker = DDS_Publisher_create_datawriter( + chatPublisher, + chatMessageTopic, + DDS_DATAWRITER_QOS_USE_TOPIC_QOS, + NULL, + DDS_STATUS_MASK_NONE); + if (!talker) { + printf("Creating datawriter failed!!\n"); + exit(-1); + } + printf("Created datawriter.\n"); + + ownID = 0; + + msg = Chat_ChatMessage__alloc(); + //checkHandle(msg, "Chat_ChatMessage__alolc"); + msg->userID = ownID; + msg->index = 0; + msg->content = DDS_string_alloc(MAX_MSG_LEN); + //checkHandle(msg->content, "DDS_string_alloc"); + snprintf(msg->content, MAX_MSG_LEN, "hello world"); + + // register a chat message + userHandle = Chat_ChatMessageDataWriter_register_instance(talker, msg); + + ns.userID = ownID; + ns.name = DDS_string_alloc(Chat_MAX_NAME+1); + //checkHandle(ns.name, "DDS_string_alloc"); + char *chatterName; + snprintf(ns.name, Chat_MAX_NAME+1, "Chatter %d", ownID); + + int j; + msg_content = (char*) malloc(MAX_MSG_LEN); + for (j < 0; j < MAX_MSG_LEN; ++j) + { + msg_content[j] = '.'; + } + + // Write user information + status = Chat_NameServiceDataWriter_write(nameServer, &ns, DDS_HANDLE_NIL); + //checkStatus(status, "Chat_ChatMessageDataWriter_write"); + + printf("Created user handle and preallocated message.\n"); + + // end init + + rttest_read_args(argc, argv); + rttest_spin(callback, NULL); + rttest_write_results(); + rttest_finish(); + + // begin teardown + + /* Remove the DataWriters */ + status = DDS_Publisher_delete_datawriter(chatPublisher, + talker); + if (status != DDS_RETCODE_OK) { + printf("Deleting datawriter failed!!\n"); + exit(-1); + } + printf("Deleted datawriter.\n"); + + /* Remove the Publisher. */ + status = DDS_DomainParticipant_delete_publisher( + dp, chatPublisher); + if (status != DDS_RETCODE_OK) { + printf("Deleting publisher failed!!\n"); + exit(-1); + } + /* De-allocate the PublisherQoS holder. */ + DDS_free(pub_qos); // Note that DDS_free recursively + // de-allocates all indirections!! + printf("Deleted publisher.\n"); + + /* Deleting the Topic. */ + status = DDS_DomainParticipant_delete_topic( + dp, chatMessageTopic); + if (status != DDS_RETCODE_OK) { + printf("Deleting topic failed. Status = %d\n", status); + exit(-1); + }; + printf("Deleted ChatMessage topic.\n"); + + /* Deleting the DomainParticipant */ + status = DDS_DomainParticipantFactory_delete_participant( + dpf, dp); + if (status != DDS_RETCODE_OK) { + printf("Deleting participant failed. Status = %d\n", status); + exit(-1); + }; + printf("Deleted Participant.\n"); + + /* Everything is fine, return normally. */ + return 0; +}; From 524436381818663e2106016d08a3c5dd641ba088 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 1 Jul 2015 22:11:13 -0700 Subject: [PATCH 11/34] rename example publisher to unsafepublisher --- realtime/CMakeLists.txt | 7 +++++-- realtime/{ExamplePublisher.hpp => UnsafePublisher.hpp} | 8 ++++---- realtime/dds_intraproc.cpp | 4 ++-- realtime/{dds_lmp.cpp => dds_unsafe_lmp.cpp} | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) rename realtime/{ExamplePublisher.hpp => UnsafePublisher.hpp} (97%) rename realtime/{dds_lmp.cpp => dds_unsafe_lmp.cpp} (89%) diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt index 3b51fca..0940bea 100644 --- a/realtime/CMakeLists.txt +++ b/realtime/CMakeLists.txt @@ -18,8 +18,11 @@ ospl_add_idl(idl/LargeMsg.idl) add_executable(dds_lms dds_lms.cpp) target_link_libraries(dds_lms ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) -add_executable(dds_lmp dds_lmp.cpp) -target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) +#add_executable(dds_lmp dds_lmp.cpp) +#target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) + +add_executable(dds_unsafe_lmp dds_unsafe_lmp.cpp) +target_link_libraries(dds_unsafe_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) find_package(Threads) if(NOT Threads_FOUND) diff --git a/realtime/ExamplePublisher.hpp b/realtime/UnsafePublisher.hpp similarity index 97% rename from realtime/ExamplePublisher.hpp rename to realtime/UnsafePublisher.hpp index 6a53b9e..6bb0292 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/UnsafePublisher.hpp @@ -3,7 +3,7 @@ #include "ccpp_LargeMsg.h" -class ExamplePublisher +class UnsafePublisher { private: LargeMsg::LargeMessageDataWriter_var data_writer; @@ -23,7 +23,7 @@ class ExamplePublisher bool teardown(); }; -bool ExamplePublisher::init() +bool UnsafePublisher::init() { this->i = 0; DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; @@ -101,7 +101,7 @@ bool ExamplePublisher::init() return true; } -void ExamplePublisher::callback() +void UnsafePublisher::callback() { checkHandle(&msg, "new LargeMsg::LargeMessage"); @@ -113,7 +113,7 @@ void ExamplePublisher::callback() } -bool ExamplePublisher::teardown() +bool UnsafePublisher::teardown() { std::cout << "Finished" << std::endl; getchar(); diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index c2e6faf..6dcecfe 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -5,9 +5,9 @@ #include #include "ExampleSubscriber.hpp" -#include "ExamplePublisher.hpp" +#include "UnsafePublisher.hpp" -ExamplePublisher pub; +UnsafePublisher pub; ExampleSubscriber sub; static void start_rt_thread(void *(*f)(void*)) diff --git a/realtime/dds_lmp.cpp b/realtime/dds_unsafe_lmp.cpp similarity index 89% rename from realtime/dds_lmp.cpp rename to realtime/dds_unsafe_lmp.cpp index 498bd59..dc58c93 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_unsafe_lmp.cpp @@ -1,11 +1,11 @@ #include #include -#include "ExamplePublisher.hpp" +#include "UnsafePublisher.hpp" #define STACK_SIZE 1024*1024*1024 -ExamplePublisher pub; +UnsafePublisher pub; void* pub_callback(void * unused) { From 44fee685dbb96c050e080717cfafd98da630a3c0 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Thu, 2 Jul 2015 11:17:37 -0700 Subject: [PATCH 12/34] guess i should vary the message size --- realtime/UnsafePublisher.hpp | 4 ++-- realtime/dds_unsafe_lmp.cpp | 12 +++++++----- tutorial_c/publisher/instrumented_main.c | 4 +++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/realtime/UnsafePublisher.hpp b/realtime/UnsafePublisher.hpp index 6bb0292..563cc92 100644 --- a/realtime/UnsafePublisher.hpp +++ b/realtime/UnsafePublisher.hpp @@ -50,7 +50,7 @@ bool UnsafePublisher::init() status = participant->get_default_topic_qos(default_topic_qos); checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + // default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; /* Register the LargeMessage Type */ LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); @@ -96,6 +96,7 @@ bool UnsafePublisher::init() this->msg.content = std::string(pow(2, 24), '.').c_str(); instance_handle = data_writer->register_instance(msg); + checkHandle(&msg, "new LargeMsg::LargeMessage"); std::cout << "Ready to send LargeMessage's" << std::endl; return true; @@ -103,7 +104,6 @@ bool UnsafePublisher::init() void UnsafePublisher::callback() { - checkHandle(&msg, "new LargeMsg::LargeMessage"); msg.seq = i; i++; diff --git a/realtime/dds_unsafe_lmp.cpp b/realtime/dds_unsafe_lmp.cpp index dc58c93..40a5f42 100644 --- a/realtime/dds_unsafe_lmp.cpp +++ b/realtime/dds_unsafe_lmp.cpp @@ -5,27 +5,29 @@ #define STACK_SIZE 1024*1024*1024 -UnsafePublisher pub; +UnsafePublisher *pub; void* pub_callback(void * unused) { - pub.callback(); + pub->callback(); } int main(int argc, char *argv[]) { - pub.init(); + pub = new UnsafePublisher; + pub->init(); rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); //rttest_lock_memory(); //rttest_prefault_stack_size(STACK_SIZE); - rttest_lock_and_prefault_dynamic(STACK_SIZE); + //rttest_lock_and_prefault_dynamic(STACK_SIZE); rttest_spin(pub_callback, NULL); rttest_write_results(); rttest_finish(); - pub.teardown(); + pub->teardown(); + delete pub; } diff --git a/tutorial_c/publisher/instrumented_main.c b/tutorial_c/publisher/instrumented_main.c index f59eb71..77de96c 100644 --- a/tutorial_c/publisher/instrumented_main.c +++ b/tutorial_c/publisher/instrumented_main.c @@ -36,7 +36,7 @@ int main ( DDS_Topic chatMessageTopic; char *chatMessageTypeName; -DDS_PublisherQos *pub_qos; + DDS_PublisherQos *pub_qos; DDS_DataWriterQos *dw_qos; DDS_Publisher chatPublisher; Chat_NameServiceDataWriter nameServer; @@ -187,6 +187,8 @@ DDS_PublisherQos *pub_qos; // end init rttest_read_args(argc, argv); + rttest_set_sched_priority(90, SCHED_RR); + rttest_spin(callback, NULL); rttest_write_results(); rttest_finish(); From d14e03288a16845ccf0973dbf5af2c48161bb8a2 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Thu, 2 Jul 2015 12:18:45 -0700 Subject: [PATCH 13/34] Message size parameterized, ready to take lots of data --- realtime/CMakeLists.txt | 8 +- realtime/UnsafePublisher.hpp | 139 ----------------------------------- realtime/dds_intraproc.cpp | 39 +++++++++- realtime/dds_unsafe_lmp.cpp | 33 --------- 4 files changed, 40 insertions(+), 179 deletions(-) delete mode 100644 realtime/UnsafePublisher.hpp delete mode 100644 realtime/dds_unsafe_lmp.cpp diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt index 0940bea..8657106 100644 --- a/realtime/CMakeLists.txt +++ b/realtime/CMakeLists.txt @@ -18,11 +18,11 @@ ospl_add_idl(idl/LargeMsg.idl) add_executable(dds_lms dds_lms.cpp) target_link_libraries(dds_lms ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) -#add_executable(dds_lmp dds_lmp.cpp) -#target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) +add_executable(dds_lmp dds_lmp.cpp) +target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) -add_executable(dds_unsafe_lmp dds_unsafe_lmp.cpp) -target_link_libraries(dds_unsafe_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) +#add_executable(dds_unsafe_lmp dds_unsafe_lmp.cpp) +#target_link_libraries(dds_unsafe_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) find_package(Threads) if(NOT Threads_FOUND) diff --git a/realtime/UnsafePublisher.hpp b/realtime/UnsafePublisher.hpp deleted file mode 100644 index 563cc92..0000000 --- a/realtime/UnsafePublisher.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#include "ccpp_dds_dcps.h" -#include "check_status.h" - -#include "ccpp_LargeMsg.h" - -class UnsafePublisher -{ - private: - LargeMsg::LargeMessageDataWriter_var data_writer; - DDS::Publisher_var publisher; - DDS::DomainParticipantFactory_var dpf; - DDS::DomainParticipant_var participant; - DDS::Topic_var large_message_topic; - char * large_message_type_name; - LargeMsg::LargeMessage msg; - DDS::ReturnCode_t status; - DDS::InstanceHandle_t instance_handle; - int i; - - public: - void callback(); - bool init(); - bool teardown(); -}; - -bool UnsafePublisher::init() -{ - this->i = 0; - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; - - /* Create Domain Participant Factory */ - this->dpf = DDS::DomainParticipantFactory::get_instance(); - checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); - - /* Create Domain Participant */ - std::cout << "Creating domain participant in publisher" << std::endl; - this->participant = dpf->create_participant( - domain, - PARTICIPANT_QOS_DEFAULT, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); - - - /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; - status = participant->get_default_topic_qos(default_topic_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); - // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - // default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; - - /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); - checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - this->large_message_type_name = large_message_ts->get_type_name(); - status = large_message_ts->register_type(participant.in(), large_message_type_name); - checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); - - /* Setup the Publisher's QoS */ - DDS::PublisherQos pub_qos; - status = participant->get_default_publisher_qos(pub_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); - pub_qos.partition.name.length(1); - pub_qos.partition.name[0] = partition_name; - - /* Create the publisher */ - this->publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); - checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); - - /* Create the Topic */ - this->large_message_topic = participant->create_topic( - topic_name, - large_message_type_name, - default_topic_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); - - /* Create Topic DataWriter */ - DDS::DataWriter_var topic_writer = publisher->create_datawriter( - large_message_topic.in(), - DATAWRITER_QOS_USE_TOPIC_QOS, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); - - /* Narrow the Topic DataWriter to be only for LargeMessage */ - this->data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); - checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); - - - this->msg.content = std::string(pow(2, 24), '.').c_str(); - instance_handle = data_writer->register_instance(msg); - checkHandle(&msg, "new LargeMsg::LargeMessage"); - - std::cout << "Ready to send LargeMessage's" << std::endl; - return true; -} - -void UnsafePublisher::callback() -{ - - msg.seq = i; - i++; - - status = data_writer->write(msg, instance_handle); - //checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); -} - - -bool UnsafePublisher::teardown() -{ - std::cout << "Finished" << std::endl; - getchar(); - /* Shutdown */ - { - DDS::string_free(msg.content); - - status = publisher->delete_datawriter(data_writer.in()); - checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); - - status = participant->delete_publisher(publisher.in()); - checkStatus(status, "DDS::DomainParticipant::delete_publisher"); - - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); - - DDS::string_free(large_message_type_name); - - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); - } - return true; -} diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index 6dcecfe..7b6533d 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -2,12 +2,11 @@ #include #include - #include #include "ExampleSubscriber.hpp" -#include "UnsafePublisher.hpp" +#include "ExamplePublisher.hpp" -UnsafePublisher pub; +ExamplePublisher pub; ExampleSubscriber sub; static void start_rt_thread(void *(*f)(void*)) @@ -61,6 +60,8 @@ void *subscriber_thread(void *unused) rttest_init_new_thread(); rttest_set_sched_priority(90, SCHED_RR); + rttest_lock_memory(); + rttest_prefault_stack_size(4096); rttest_spin(sub_callback, NULL); @@ -71,7 +72,39 @@ void *subscriber_thread(void *unused) int main(int argc, char *argv[]) { + int c; + + unsigned int message_length; + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } + + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) + { + switch(c) + { + case 'l': + message_length = std::stoul(std::string(optarg)); + break; + default: + break; + } + } + rttest_read_args(argc, argv); + + pub.message_size = message_length; rttest_read_args(argc, argv); + + rttest_lock_memory(); + rttest_prefault_stack_size(message_length + 4096); start_rt_thread(&subscriber_thread); publisher_thread(NULL); } diff --git a/realtime/dds_unsafe_lmp.cpp b/realtime/dds_unsafe_lmp.cpp deleted file mode 100644 index 40a5f42..0000000 --- a/realtime/dds_unsafe_lmp.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include - -#include -#include "UnsafePublisher.hpp" - -#define STACK_SIZE 1024*1024*1024 - -UnsafePublisher *pub; - -void* pub_callback(void * unused) -{ - pub->callback(); -} - -int main(int argc, char *argv[]) -{ - pub = new UnsafePublisher; - pub->init(); - - rttest_read_args(argc, argv); - rttest_set_sched_priority(90, SCHED_RR); - //rttest_lock_memory(); - //rttest_prefault_stack_size(STACK_SIZE); - //rttest_lock_and_prefault_dynamic(STACK_SIZE); - - rttest_spin(pub_callback, NULL); - - rttest_write_results(); - rttest_finish(); - - pub->teardown(); - delete pub; -} From 7a77f7abae75c5de248fb4a7f6453fb16a181814 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Thu, 2 Jul 2015 13:06:12 -0700 Subject: [PATCH 14/34] add back examples --- realtime/ExamplePublisher.hpp | 144 ++++++++++++++++++++++++++++++++++ realtime/dds_lmp.cpp | 57 ++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 realtime/ExamplePublisher.hpp create mode 100644 realtime/dds_lmp.cpp diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp new file mode 100644 index 0000000..44ed83f --- /dev/null +++ b/realtime/ExamplePublisher.hpp @@ -0,0 +1,144 @@ +#include "ccpp_dds_dcps.h" +#include "check_status.h" + +#include "ccpp_LargeMsg.h" + + +class ExamplePublisher +{ + private: + LargeMsg::LargeMessageDataWriter_var data_writer; + DDS::Publisher_var publisher; + DDS::DomainParticipantFactory_var dpf; + DDS::DomainParticipant_var participant; + DDS::Topic_var large_message_topic; + char * large_message_type_name; + LargeMsg::LargeMessage msg; + DDS::ReturnCode_t status; + DDS::InstanceHandle_t instance_handle; + int i; + + public: + ExamplePublisher(unsigned int message_size = 16777216); + unsigned int message_size; + void callback(); + bool init(); + bool teardown(); +}; + +ExamplePublisher::ExamplePublisher(unsigned int message_size) : message_size(message_size) +{ +} + +bool ExamplePublisher::init() +{ + this->i = 0; + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + this->dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + std::cout << "Creating domain participant in publisher" << std::endl; + this->participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + + /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + // default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + this->large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Publisher's QoS */ + DDS::PublisherQos pub_qos; + status = participant->get_default_publisher_qos(pub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); + pub_qos.partition.name.length(1); + pub_qos.partition.name[0] = partition_name; + + /* Create the publisher */ + this->publisher = participant->create_publisher(pub_qos, NULL, DDS::STATUS_MASK_NONE); + checkHandle(publisher.in(), "DDS::DomainParticipant::create_publisher"); + + /* Create the Topic */ + this->large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic DataWriter */ + DDS::DataWriter_var topic_writer = publisher->create_datawriter( + large_message_topic.in(), + DATAWRITER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_writer.in(), "DDS::Publisher::create_datawriter(LargeMessage)"); + + /* Narrow the Topic DataWriter to be only for LargeMessage */ + this->data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); + checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); + + + this->msg.content = std::string(this->message_size, '.').c_str(); + instance_handle = data_writer->register_instance(msg); + checkHandle(&msg, "new LargeMsg::LargeMessage"); + + std::cout << "Ready to send LargeMessage's" << std::endl; + return true; +} + +void ExamplePublisher::callback() +{ + + msg.seq = i; + i++; + + status = data_writer->write(msg, instance_handle); + //checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); +} + + +bool ExamplePublisher::teardown() +{ + std::cout << "Finished" << std::endl; + getchar(); + /* Shutdown */ + { + status = publisher->delete_datawriter(data_writer.in()); + checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + + status = participant->delete_publisher(publisher.in()); + checkStatus(status, "DDS::DomainParticipant::delete_publisher"); + + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + + DDS::string_free(large_message_type_name); + + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } + return true; +} diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp new file mode 100644 index 0000000..0c40f73 --- /dev/null +++ b/realtime/dds_lmp.cpp @@ -0,0 +1,57 @@ +#include + +#include +#include "ExamplePublisher.hpp" + +ExamplePublisher pub; + +void* pub_callback(void * unused) +{ + pub.callback(); +} + +int main(int argc, char *argv[]) +{ + int c; + + unsigned int message_length; + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } + + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) + { + switch(c) + { + case 'l': + message_length = std::stoul(std::string(optarg)); + break; + default: + break; + } + } + rttest_read_args(argc, argv); + + pub.message_size = message_length; + pub.init(); + + rttest_set_sched_priority(90, SCHED_RR); + rttest_lock_memory(); + rttest_prefault_stack_size(message_length + 4096); + //rttest_lock_and_prefault_dynamic(STACK_SIZE); + + rttest_spin(pub_callback, NULL); + + rttest_write_results(); + rttest_finish(); + + pub.teardown(); +} From 7754b62aabb0122a9ace0c75febe0a45cd82f05e Mon Sep 17 00:00:00 2001 From: Jackie Date: Thu, 2 Jul 2015 18:06:19 -0700 Subject: [PATCH 15/34] Proper memlocking now --- large_message_cpp/dds_lms.cpp | 3 + realtime/ExamplePublisher.hpp | 52 ++++--- realtime/ExampleSubscriber.hpp | 253 +++++++++++++++++---------------- realtime/check_status.h | 2 +- realtime/dds_intraproc.cpp | 27 ++-- realtime/dds_lmp.cpp | 43 ++++-- realtime/dds_lms.cpp | 5 + 7 files changed, 221 insertions(+), 164 deletions(-) diff --git a/large_message_cpp/dds_lms.cpp b/large_message_cpp/dds_lms.cpp index eec6999..1761916 100644 --- a/large_message_cpp/dds_lms.cpp +++ b/large_message_cpp/dds_lms.cpp @@ -14,6 +14,7 @@ static void catch_function(int signo) { int main(int argc, char *argv[]) { + int msgs_received = 0; /* Register a signal handler so DDS doesn't just sit there... */ if (signal(SIGINT, catch_function) == SIG_ERR) { @@ -111,6 +112,7 @@ int main(int argc, char *argv[]) { LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; + ++msgs_received; } status = data_reader->return_loan(large_msg_seq, sample_info_seq); @@ -124,6 +126,7 @@ int main(int argc, char *argv[]) #endif } + std::cout << "Received " << msgs_received << " messages." << std::endl; /* Shutdown */ { status = participant->delete_subscriber(subscriber.in()); diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp index 44ed83f..ab5ff92 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/ExamplePublisher.hpp @@ -15,7 +15,16 @@ class ExamplePublisher char * large_message_type_name; LargeMsg::LargeMessage msg; DDS::ReturnCode_t status; + // DDS::InstanceHandle_t instance_handle; + DDS::DomainId_t domain; + const char * partition_name; + const char * topic_name; + DDS::TopicQos default_topic_qos; + LargeMsg::LargeMessageTypeSupport_var large_message_ts; + DDS::PublisherQos pub_qos; + DDS::DataWriter_var topic_writer; DDS::InstanceHandle_t instance_handle; + int i; public: @@ -33,9 +42,9 @@ ExamplePublisher::ExamplePublisher(unsigned int message_size) : message_size(mes bool ExamplePublisher::init() { this->i = 0; - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; + domain = DDS::DOMAIN_ID_DEFAULT; + partition_name = "Default"; + topic_name = "big_chatter"; /* Create Domain Participant Factory */ this->dpf = DDS::DomainParticipantFactory::get_instance(); @@ -53,21 +62,19 @@ bool ExamplePublisher::init() /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; status = participant->get_default_topic_qos(default_topic_qos); checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - // default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + this->large_message_ts = new LargeMsg::LargeMessageTypeSupport(); checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); this->large_message_type_name = large_message_ts->get_type_name(); status = large_message_ts->register_type(participant.in(), large_message_type_name); checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); /* Setup the Publisher's QoS */ - DDS::PublisherQos pub_qos; status = participant->get_default_publisher_qos(pub_qos); checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); pub_qos.partition.name.length(1); @@ -88,7 +95,7 @@ bool ExamplePublisher::init() checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); /* Create Topic DataWriter */ - DDS::DataWriter_var topic_writer = publisher->create_datawriter( + topic_writer = publisher->create_datawriter( large_message_topic.in(), DATAWRITER_QOS_USE_TOPIC_QOS, NULL, @@ -100,9 +107,7 @@ bool ExamplePublisher::init() this->data_writer = LargeMsg::LargeMessageDataWriter::_narrow(topic_writer.in()); checkHandle(data_writer.in(), "LargeMsg::LargeMessageDataWriter::_narrow"); - this->msg.content = std::string(this->message_size, '.').c_str(); - instance_handle = data_writer->register_instance(msg); checkHandle(&msg, "new LargeMsg::LargeMessage"); std::cout << "Ready to send LargeMessage's" << std::endl; @@ -111,34 +116,35 @@ bool ExamplePublisher::init() void ExamplePublisher::callback() { - msg.seq = i; - i++; + ++i; + instance_handle = data_writer->register_instance(msg); status = data_writer->write(msg, instance_handle); - //checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); + + checkStatus(status, "LargeMsg::LargeMessageDataWriter::write"); } bool ExamplePublisher::teardown() { std::cout << "Finished" << std::endl; - getchar(); + //getchar(); /* Shutdown */ { - status = publisher->delete_datawriter(data_writer.in()); - checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + status = publisher->delete_datawriter(data_writer.in()); + checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); - status = participant->delete_publisher(publisher.in()); - checkStatus(status, "DDS::DomainParticipant::delete_publisher"); + status = participant->delete_publisher(publisher.in()); + checkStatus(status, "DDS::DomainParticipant::delete_publisher"); - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); - DDS::string_free(large_message_type_name); + DDS::string_free(large_message_type_name); - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); } return true; } diff --git a/realtime/ExampleSubscriber.hpp b/realtime/ExampleSubscriber.hpp index d455e0a..564b17b 100644 --- a/realtime/ExampleSubscriber.hpp +++ b/realtime/ExampleSubscriber.hpp @@ -5,143 +5,152 @@ class ExampleSubscriber { - private: - DDS::DomainParticipantFactory_var dpf; - DDS::DomainParticipant_var participant; - DDS::Subscriber_var subscriber; - LargeMsg::LargeMessageDataReader_var data_reader; - DDS::Topic_var large_message_topic; - char * large_message_type_name; - LargeMsg::LargeMessageSeq_var large_msg_seq; - DDS::SampleInfoSeq_var sample_info_seq; - bool subscriber_running; - DDS::ReturnCode_t status; - - public: - void callback(); - bool init(); - bool teardown(); + private: + DDS::DomainParticipantFactory_var dpf; + DDS::DomainParticipant_var participant; + DDS::Subscriber_var subscriber; + LargeMsg::LargeMessageDataReader_var data_reader; + DDS::Topic_var large_message_topic; + char * large_message_type_name; + LargeMsg::LargeMessageSeq_var large_msg_seq; + DDS::SampleInfoSeq_var sample_info_seq; + bool subscriber_running; + DDS::ReturnCode_t status; + unsigned long msgs_count; + DDS::DomainId_t domain; + //LargeMsg::LargeMessage *msg; + const char * partition_name; + const char * topic_name; + DDS::TopicQos default_topic_qos; + LargeMsg::LargeMessageTypeSupport_var large_message_ts; + DDS::SubscriberQos sub_qos; + DDS::DataReader_var topic_reader; + + public: + void callback(); + bool init(); + bool teardown(); }; bool ExampleSubscriber::init() { - DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; - const char * partition_name = "Default"; - const char * topic_name = "big_chatter"; - - /* Create Domain Participant Factory */ - this->dpf = DDS::DomainParticipantFactory::get_instance(); - checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); - - /* Create Domain Participant */ - std::cout << "Creating domain participant in subscriber" << std::endl; - this->participant = dpf->create_participant( - domain, - PARTICIPANT_QOS_DEFAULT, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); - - - /* Create a default QoS for Topics */ - DDS::TopicQos default_topic_qos; - status = participant->get_default_topic_qos(default_topic_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); - // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; - default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; - - /* Register the LargeMessage Type */ - LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); - checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - this->large_message_type_name = large_message_ts->get_type_name(); - status = large_message_ts->register_type(participant.in(), large_message_type_name); - checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); - - /* Setup the Subscribers's QoS */ - DDS::SubscriberQos sub_qos; - status = participant->get_default_subscriber_qos(sub_qos); - checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); - sub_qos.partition.name.length(1); - sub_qos.partition.name[0] = partition_name; - - /* Create the subscriber */ - this->subscriber = participant->create_subscriber( - sub_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); - - /* Create the Topic */ - this->large_message_topic = participant->create_topic( - topic_name, - large_message_type_name, - default_topic_qos, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); - - /* Create Topic specific DataReader */ - DDS::DataReader_var topic_reader = subscriber->create_datareader( - large_message_topic.in(), - DATAREADER_QOS_USE_TOPIC_QOS, - NULL, - DDS::STATUS_MASK_NONE - ); - checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); - - /* Narrow topic_reader down to LargeMessage specific DataReader */ - this->data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); - checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); - - this->large_msg_seq = new LargeMsg::LargeMessageSeq(); - this->sample_info_seq = new DDS::SampleInfoSeq(); - - std::cout << "Polling DataReader..." << std::endl; - return true; + this->msgs_count = 0; + domain = DDS::DOMAIN_ID_DEFAULT; + partition_name = "Default"; + topic_name = "big_chatter"; + + /* Create Domain Participant Factory */ + this->dpf = DDS::DomainParticipantFactory::get_instance(); + checkHandle(dpf.in(), "DDS::DomainParticipantFactory::get_instance"); + + /* Create Domain Participant */ + std::cout << "Creating domain participant in subscriber" << std::endl; + this->participant = dpf->create_participant( + domain, + PARTICIPANT_QOS_DEFAULT, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(participant.in(), "DDS::DomainParticipantFactory::create_participant"); + + + /* Create a default QoS for Topics */ + status = participant->get_default_topic_qos(default_topic_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); + // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; + default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; + + /* Register the LargeMessage Type */ + large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); + this->large_message_type_name = large_message_ts->get_type_name(); + status = large_message_ts->register_type(participant.in(), large_message_type_name); + checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); + + /* Setup the Subscribers's QoS */ + status = participant->get_default_subscriber_qos(sub_qos); + checkStatus(status, "DDS::DomainParticipant::get_default_subscriber_qos"); + sub_qos.partition.name.length(1); + sub_qos.partition.name[0] = partition_name; + + /* Create the subscriber */ + this->subscriber = participant->create_subscriber( + sub_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(subscriber.in(), "DDS::DomainParticipant::create_subscriber"); + + /* Create the Topic */ + this->large_message_topic = participant->create_topic( + topic_name, + large_message_type_name, + default_topic_qos, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); + + /* Create Topic specific DataReader */ + topic_reader = subscriber->create_datareader( + large_message_topic.in(), + DATAREADER_QOS_USE_TOPIC_QOS, + NULL, + DDS::STATUS_MASK_NONE + ); + checkHandle(topic_reader.in(), "DDS::Subscriber::create_datareader"); + + /* Narrow topic_reader down to LargeMessage specific DataReader */ + this->data_reader = LargeMsg::LargeMessageDataReader::_narrow(topic_reader.in()); + checkHandle(data_reader.in(), "LargeMsg::LargeMessageDataReader::_narrow"); + + this->large_msg_seq = new LargeMsg::LargeMessageSeq(); + this->sample_info_seq = new DDS::SampleInfoSeq(); + + std::cout << "Polling DataReader..." << std::endl; + return true; } void ExampleSubscriber::callback() { - status = data_reader->take( - large_msg_seq, - sample_info_seq, - DDS::LENGTH_UNLIMITED, - DDS::ANY_SAMPLE_STATE, - DDS::ANY_VIEW_STATE, - DDS::ALIVE_INSTANCE_STATE - ); - checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); - - /* - for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) - { - LargeMsg::LargeMessage *msg = &(large_msg_seq[i]); - std::cout << "[" << msg->seq << "]: " << strlen(msg->content.m_ptr) << std::endl; - } - */ - - status = data_reader->return_loan(large_msg_seq, sample_info_seq); - checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); + status = data_reader->take( + large_msg_seq, + sample_info_seq, + DDS::LENGTH_UNLIMITED, + DDS::ANY_SAMPLE_STATE, + DDS::ANY_VIEW_STATE, + DDS::ALIVE_INSTANCE_STATE + ); + checkStatus(status, "LargeMsg::LargeMessageDataReader::take"); + + for (DDS::ULong i = 0; i < large_msg_seq->length(); i++) + { + //msg = &(large_msg_seq[i]); + ++this->msgs_count; + } + + status = data_reader->return_loan(large_msg_seq, sample_info_seq); + checkStatus(status, "LargeMsg::LargeMessageDataReader::return_loan"); } bool ExampleSubscriber::teardown() { - // TODO investigate why preconditions not met - /* Shutdown */ - status = participant->delete_subscriber(subscriber.in()); - //checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + std::cout << "Subscriber received " << this->msgs_count << " messages." << std::endl; + /* Shutdown */ + if (subscriber.in() != NULL) { + status = participant->delete_subscriber(subscriber.in()); + checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + } - status = participant->delete_topic(large_message_topic.in()); - //checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); - DDS::string_free(large_message_type_name); + DDS::string_free(large_message_type_name); - status = dpf->delete_participant(participant.in()); - //checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); - return true; + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + + return true; } diff --git a/realtime/check_status.h b/realtime/check_status.h index 2f5b804..eefab3d 100644 --- a/realtime/check_status.h +++ b/realtime/check_status.h @@ -30,7 +30,7 @@ void checkStatus(DDS::ReturnCode_t status, const char *info) if (status != DDS::RETCODE_OK && status != DDS::RETCODE_NO_DATA) { std::cerr << "Error in " << info << ": " << getErrorName(status) << std::endl; - exit (1); + //exit (1); } } diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index 7b6533d..fffba08 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -8,6 +8,7 @@ ExamplePublisher pub; ExampleSubscriber sub; +unsigned int message_length; static void start_rt_thread(void *(*f)(void*)) { @@ -22,12 +23,12 @@ static void start_rt_thread(void *(*f)(void*)) } /* Set the requested stacksize for this thread */ - // put this in rttest - /*if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + MAX_SAFE_STACK)) + // put this in rttest? + if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 2*message_length + sizeof(sub))) { fprintf(stderr, "Couldn't set requested stack size for pthread"); exit(1); - }*/ + } /* And finally start the actual thread */ pthread_create(&thread, &attr, f, NULL); @@ -59,9 +60,7 @@ void *subscriber_thread(void *unused) sub.init(); rttest_init_new_thread(); - rttest_set_sched_priority(90, SCHED_RR); - rttest_lock_memory(); - rttest_prefault_stack_size(4096); + rttest_set_sched_priority(98, SCHED_RR); rttest_spin(sub_callback, NULL); @@ -74,7 +73,6 @@ int main(int argc, char *argv[]) { int c; - unsigned int message_length; // l stands for message length opterr = 0; optind = 1; @@ -101,10 +99,21 @@ int main(int argc, char *argv[]) rttest_read_args(argc, argv); pub.message_size = message_length; + size_t stack_size = message_length*2 + sizeof(pub) + sizeof(sub); + size_t pool_size = 2*message_length; + + rttest_lock_and_prefault_dynamic(pool_size); + rttest_prefault_stack_size(stack_size); + rttest_read_args(argc, argv); - rttest_lock_memory(); - rttest_prefault_stack_size(message_length + 4096); start_rt_thread(&subscriber_thread); + + rttest_set_sched_priority(98, SCHED_RR); + publisher_thread(NULL); + for (int i = 0; i < argc; ++i) + { + free(argv_copy[i]); + } } diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index 0c40f73..e293d0d 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -3,11 +3,11 @@ #include #include "ExamplePublisher.hpp" -ExamplePublisher pub; +ExamplePublisher *pub; void* pub_callback(void * unused) { - pub.callback(); + pub->callback(); } int main(int argc, char *argv[]) @@ -40,18 +40,43 @@ int main(int argc, char *argv[]) } rttest_read_args(argc, argv); - pub.message_size = message_length; - pub.init(); + pub = new ExamplePublisher; + pub->message_size = message_length; - rttest_set_sched_priority(90, SCHED_RR); - rttest_lock_memory(); - rttest_prefault_stack_size(message_length + 4096); - //rttest_lock_and_prefault_dynamic(STACK_SIZE); + //size_t pool_size = message_length; + + /* + if (rttest_lock_and_prefault_dynamic(pool_size) != 0) + { + std::cout << "Failed to lock dynamic memory." << std::endl; + }*/ + + pub->init(); + + /*struct timespec t; + t.tv_sec = 2; + t.tv_nsec = 0;*/ + + if (rttest_set_sched_priority(98, SCHED_RR) != 0) + { + std::cout << "Failed to set realtime priority of thread" << std::endl; + } + + + if (rttest_lock_memory() != 0) + { + perror("Failed to lock memory."); + } + size_t stack_size = 1024*1024 + message_length + sizeof(*pub); + rttest_prefault_stack_size(stack_size); + + + //clock_nanosleep(0, 0, &t, 0); rttest_spin(pub_callback, NULL); rttest_write_results(); rttest_finish(); - pub.teardown(); + pub->teardown(); } diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index 4187b09..45229c1 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -17,6 +17,11 @@ int main(int argc, char *argv[]) rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); + size_t pool_size = 1024*1024*1024; + size_t stack_size = sizeof(sub) + 1024*1024; + rttest_lock_and_prefault_dynamic(pool_size); + rttest_prefault_stack_size(stack_size); + rttest_spin(sub_callback, NULL); rttest_write_results(); From 840bba65e1803bb5a9062d2500f3e53d2d83ce87 Mon Sep 17 00:00:00 2001 From: Jackie Date: Mon, 6 Jul 2015 16:15:42 -0700 Subject: [PATCH 16/34] DDS objects are too darn big --- realtime/ExamplePublisher.hpp | 48 +++++++++++-------------- realtime/ExampleSubscriber.hpp | 25 ++++++------- realtime/dds_intraproc.cpp | 42 +++++++++++++--------- realtime/dds_lmp.cpp | 66 +++++++++++++++------------------- realtime/dds_lms.cpp | 23 ++++++++---- 5 files changed, 106 insertions(+), 98 deletions(-) diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp index ab5ff92..b4867fe 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/ExamplePublisher.hpp @@ -7,27 +7,19 @@ class ExamplePublisher { private: - LargeMsg::LargeMessageDataWriter_var data_writer; DDS::Publisher_var publisher; DDS::DomainParticipantFactory_var dpf; DDS::DomainParticipant_var participant; DDS::Topic_var large_message_topic; - char * large_message_type_name; - LargeMsg::LargeMessage msg; DDS::ReturnCode_t status; - // DDS::InstanceHandle_t instance_handle; - DDS::DomainId_t domain; - const char * partition_name; - const char * topic_name; - DDS::TopicQos default_topic_qos; - LargeMsg::LargeMessageTypeSupport_var large_message_ts; - DDS::PublisherQos pub_qos; - DDS::DataWriter_var topic_writer; - DDS::InstanceHandle_t instance_handle; + public: + + DDS::InstanceHandle_t instance_handle; + LargeMsg::LargeMessage msg; + LargeMsg::LargeMessageDataWriter_var data_writer; int i; - public: ExamplePublisher(unsigned int message_size = 16777216); unsigned int message_size; void callback(); @@ -42,9 +34,9 @@ ExamplePublisher::ExamplePublisher(unsigned int message_size) : message_size(mes bool ExamplePublisher::init() { this->i = 0; - domain = DDS::DOMAIN_ID_DEFAULT; - partition_name = "Default"; - topic_name = "big_chatter"; + DDS::DomainId_t domain = DDS::DOMAIN_ID_DEFAULT; + const char * partition_name = "Default"; + const char * topic_name = "big_chatter"; /* Create Domain Participant Factory */ this->dpf = DDS::DomainParticipantFactory::get_instance(); @@ -62,19 +54,21 @@ bool ExamplePublisher::init() /* Create a default QoS for Topics */ + DDS::TopicQos default_topic_qos; status = participant->get_default_topic_qos(default_topic_qos); checkStatus(status, "DDS::DomainParticipant::get_default_topic_qos"); // default_topic_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; default_topic_qos.reliability.kind = DDS::BEST_EFFORT_RELIABILITY_QOS; /* Register the LargeMessage Type */ - this->large_message_ts = new LargeMsg::LargeMessageTypeSupport(); + LargeMsg::LargeMessageTypeSupport_var large_message_ts = new LargeMsg::LargeMessageTypeSupport(); checkHandle(large_message_ts.in(), "new LargeMessageTypeSupport"); - this->large_message_type_name = large_message_ts->get_type_name(); + const char * large_message_type_name = large_message_ts->get_type_name(); status = large_message_ts->register_type(participant.in(), large_message_type_name); checkStatus(status, "LargeMsg::LargeMessageTypeSupport::register_type"); /* Setup the Publisher's QoS */ + DDS::PublisherQos pub_qos; status = participant->get_default_publisher_qos(pub_qos); checkStatus(status, "DDS::DomainParticipant::get_default_publisher_qos"); pub_qos.partition.name.length(1); @@ -95,7 +89,7 @@ bool ExamplePublisher::init() checkHandle(large_message_topic.in(), "DDS::DomainParticipant::create_topic(LargeMessage)"); /* Create Topic DataWriter */ - topic_writer = publisher->create_datawriter( + DDS::DataWriter_var topic_writer = publisher->create_datawriter( large_message_topic.in(), DATAWRITER_QOS_USE_TOPIC_QOS, NULL, @@ -116,9 +110,9 @@ bool ExamplePublisher::init() void ExamplePublisher::callback() { - msg.seq = i; + this->msg.seq = this->i; ++i; - instance_handle = data_writer->register_instance(msg); + this->instance_handle = this->data_writer->register_instance(msg); status = data_writer->write(msg, instance_handle); @@ -132,18 +126,18 @@ bool ExamplePublisher::teardown() //getchar(); /* Shutdown */ { - status = publisher->delete_datawriter(data_writer.in()); - checkStatus(status, "DDS::Publisher::delete_datawriter(data_writer)"); + status = this->publisher->delete_datawriter(this->data_writer.in()); + checkStatus(this->status, "DDS::Publisher::delete_datawriter(data_writer)"); - status = participant->delete_publisher(publisher.in()); + status = this->participant->delete_publisher(publisher.in()); checkStatus(status, "DDS::DomainParticipant::delete_publisher"); - status = participant->delete_topic(large_message_topic.in()); + status = participant->delete_topic(this->large_message_topic.in()); checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); - DDS::string_free(large_message_type_name); + //DDS::string_free(this->large_message_type_name); - status = dpf->delete_participant(participant.in()); + status = this->dpf->delete_participant(participant.in()); checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); } return true; diff --git a/realtime/ExampleSubscriber.hpp b/realtime/ExampleSubscriber.hpp index 564b17b..3aa0513 100644 --- a/realtime/ExampleSubscriber.hpp +++ b/realtime/ExampleSubscriber.hpp @@ -16,9 +16,7 @@ class ExampleSubscriber DDS::SampleInfoSeq_var sample_info_seq; bool subscriber_running; DDS::ReturnCode_t status; - unsigned long msgs_count; DDS::DomainId_t domain; - //LargeMsg::LargeMessage *msg; const char * partition_name; const char * topic_name; DDS::TopicQos default_topic_qos; @@ -27,6 +25,7 @@ class ExampleSubscriber DDS::DataReader_var topic_reader; public: + unsigned long msgs_count; void callback(); bool init(); bool teardown(); @@ -136,20 +135,22 @@ void ExampleSubscriber::callback() bool ExampleSubscriber::teardown() { - std::cout << "Subscriber received " << this->msgs_count << " messages." << std::endl; /* Shutdown */ - if (subscriber.in() != NULL) { - status = participant->delete_subscriber(subscriber.in()); - checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); - } + if (participant != NULL) + { + if (subscriber.in() != NULL) { + status = participant->delete_subscriber(subscriber.in()); + checkStatus(status, "DDS::DomainParticipant::delete_subscriber"); + } - status = participant->delete_topic(large_message_topic.in()); - checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); + status = participant->delete_topic(large_message_topic.in()); + checkStatus(status, "DDS::DomainParticipant::delete_topic (large_message_topic)"); - DDS::string_free(large_message_type_name); + status = dpf->delete_participant(participant.in()); + checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + } - status = dpf->delete_participant(participant.in()); - checkStatus(status, "DDS::DomainParticipantFactory::delete_participant"); + DDS::string_free(large_message_type_name); return true; } diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index fffba08..9f77928 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -6,8 +6,8 @@ #include "ExampleSubscriber.hpp" #include "ExamplePublisher.hpp" -ExamplePublisher pub; -ExampleSubscriber sub; +ExamplePublisher *pub; +ExampleSubscriber *sub; unsigned int message_length; static void start_rt_thread(void *(*f)(void*)) @@ -24,7 +24,7 @@ static void start_rt_thread(void *(*f)(void*)) /* Set the requested stacksize for this thread */ // put this in rttest? - if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 2*message_length + sizeof(sub))) + if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 2*message_length + sizeof(*sub))) { fprintf(stderr, "Couldn't set requested stack size for pthread"); exit(1); @@ -36,36 +36,37 @@ static void start_rt_thread(void *(*f)(void*)) void* pub_callback(void * unused) { - pub.callback(); + if (pub != NULL) + pub->callback(); } void* sub_callback(void * unused) { - sub.callback(); + if (sub != NULL) + sub->callback(); } void *publisher_thread(void *unused) { - pub.init(); - rttest_spin(pub_callback, NULL); rttest_write_results_file("rttest_publisher_results"); - pub.teardown(); + if (pub != NULL) + pub->teardown(); rttest_finish(); } void *subscriber_thread(void *unused) { - sub.init(); - rttest_init_new_thread(); rttest_set_sched_priority(98, SCHED_RR); rttest_spin(sub_callback, NULL); rttest_write_results_file("rttest_subscriber_results"); - sub.teardown(); + std::cout << "Subscriber received " << sub->msgs_count << " messages." << std::endl; + /*if (sub != NULL) + sub->teardown();*/ rttest_finish(); } @@ -98,22 +99,31 @@ int main(int argc, char *argv[]) } rttest_read_args(argc, argv); - pub.message_size = message_length; - size_t stack_size = message_length*2 + sizeof(pub) + sizeof(sub); + pub = new ExamplePublisher(); + pub->message_size = message_length; + pub->init(); + sub = new ExampleSubscriber(); + sub->init(); + size_t stack_size = message_length*2 + sizeof(*pub) + sizeof(*sub); size_t pool_size = 2*message_length; - rttest_lock_and_prefault_dynamic(pool_size); + if (rttest_lock_and_prefault_dynamic(pool_size) != 0) + { + perror("Failed to lock dynamic memory. Process might not be real-time safe"); + } rttest_prefault_stack_size(stack_size); - rttest_read_args(argc, argv); - start_rt_thread(&subscriber_thread); rttest_set_sched_priority(98, SCHED_RR); publisher_thread(NULL); + /* for (int i = 0; i < argc; ++i) { free(argv_copy[i]); } + */ + + //delete sub; } diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index e293d0d..f57a75f 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "ExamplePublisher.hpp" @@ -12,64 +13,54 @@ void* pub_callback(void * unused) int main(int argc, char *argv[]) { - int c; - - unsigned int message_length; - // l stands for message length - opterr = 0; - optind = 1; - int argc_copy = argc; - char *argv_copy[argc]; - for (int i = 0; i < argc; ++i) + unsigned int message_length = 1; { - size_t len = strlen(argv[i]); - argv_copy[i] = (char*) malloc(len); - memcpy(argv_copy[i], argv[i], len); - } + int c; + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } - while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) - { - switch(c) + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) { - case 'l': - message_length = std::stoul(std::string(optarg)); - break; - default: - break; + switch(c) + { + case 'l': + message_length = std::stoul(std::string(optarg)); + break; + default: + break; + } } } rttest_read_args(argc, argv); + //getchar(); + pub = new ExamplePublisher; pub->message_size = message_length; - //size_t pool_size = message_length; - - /* - if (rttest_lock_and_prefault_dynamic(pool_size) != 0) - { - std::cout << "Failed to lock dynamic memory." << std::endl; - }*/ - pub->init(); - /*struct timespec t; - t.tv_sec = 2; - t.tv_nsec = 0;*/ - if (rttest_set_sched_priority(98, SCHED_RR) != 0) { std::cout << "Failed to set realtime priority of thread" << std::endl; } - if (rttest_lock_memory() != 0) + if (rttest_lock_and_prefault_dynamic(pool_size) != 0) { - perror("Failed to lock memory."); + perror("Failed to lock dynamic memory"); } - size_t stack_size = 1024*1024 + message_length + sizeof(*pub); - rttest_prefault_stack_size(stack_size); + //rttest_prefault_stack_size(stack_size); //clock_nanosleep(0, 0, &t, 0); @@ -79,4 +70,5 @@ int main(int argc, char *argv[]) rttest_finish(); pub->teardown(); + delete pub; } diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index 45229c1..0a00ef4 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -1,25 +1,34 @@ #include +#include #include #include "ExampleSubscriber.hpp" -ExampleSubscriber sub; +ExampleSubscriber *sub; void* sub_callback(void * unused) { - sub.callback(); + sub->callback(); } int main(int argc, char *argv[]) { - sub.init(); + sub = new ExampleSubscriber(); + sub->init(); rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); size_t pool_size = 1024*1024*1024; - size_t stack_size = sizeof(sub) + 1024*1024; - rttest_lock_and_prefault_dynamic(pool_size); + size_t stack_size = sizeof(*sub) + 1024*1024; + /* + getchar(); + if (rttest_lock_and_prefault_dynamic(pool_size) != 0) + { + perror("Failed to lock memory"); + } + */ + rttest_prefault_stack_size(stack_size); rttest_spin(sub_callback, NULL); @@ -27,5 +36,7 @@ int main(int argc, char *argv[]) rttest_write_results(); rttest_finish(); - sub.teardown(); + std::cout << "Subscriber received " << sub->msgs_count << " messages." << std::endl; + sub->teardown(); + delete sub; } From be1ff04324080f9577cdc529f86cf49ab6c19d1d Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Mon, 6 Jul 2015 16:27:18 -0700 Subject: [PATCH 17/34] C examples --- realtime_c/CMakeLists.txt | 21 +++ realtime_c/ExamplePublisher.hpp | 239 +++++++++++++++++++++++++++++++ realtime_c/ExampleSubscriber.hpp | 159 ++++++++++++++++++++ realtime_c/LargeMsg.idl | 7 + realtime_c/rt_publisher.cpp | 29 ++++ realtime_c/rt_subscriber.cpp | 29 ++++ 6 files changed, 484 insertions(+) create mode 100644 realtime_c/CMakeLists.txt create mode 100644 realtime_c/ExamplePublisher.hpp create mode 100644 realtime_c/ExampleSubscriber.hpp create mode 100644 realtime_c/LargeMsg.idl create mode 100644 realtime_c/rt_publisher.cpp create mode 100644 realtime_c/rt_subscriber.cpp diff --git a/realtime_c/CMakeLists.txt b/realtime_c/CMakeLists.txt new file mode 100644 index 0000000..57110f4 --- /dev/null +++ b/realtime_c/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8) +project(realtime_c) + +find_package(rttest REQUIRED) + +find_package(opensplice REQUIRED) + +# find_package only exposes the c++ include directories but not the c headers +include_directories(c /usr/include/opensplice/dcps/C/SAC ${OPENSPLICE_INCLUDE_DIRS} ${rttest_INCLUDE_DIRS}) +link_directories(${OPENSPLICE_LIBRARY_DIRS} ${rttest_LIBRARY_DIR}) + +set(MSG_C_FILES c/LargeMsgSacDcps.c c/LargeMsgSplDcps.c) + +add_executable(publisher rt_publisher.cpp ${MSG_C_FILES}) +target_link_libraries(publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) + +add_executable(subscriber rt_subscriber.cpp ${MSG_C_FILES}) +target_link_libraries(subscriber ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) + +#add_executable(intraproc rt_intraproc.cpp ${MSG_C_FILES}) +#target_link_libraries(intraproc ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) diff --git a/realtime_c/ExamplePublisher.hpp b/realtime_c/ExamplePublisher.hpp new file mode 100644 index 0000000..840f261 --- /dev/null +++ b/realtime_c/ExamplePublisher.hpp @@ -0,0 +1,239 @@ +#include "dds_dcps.h" +#include "LargeMsg.h" +#include "check_status.h" +#include "unistd.h" + +#define LargeMsg_MAX_NAME 128 +#define MAX_MSG_LEN 16777216 + +class ExamplePublisher +{ + private: + DDS_DomainParticipantFactory dpf; + DDS_DomainParticipant dp; + DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; + LargeMsg_LargeMessageTypeSupport chatMessageTS; + DDS_Topic chatMessageTopic; + char *chatMessageTypeName; + + DDS_PublisherQos *pub_qos; + DDS_DataWriterQos *dw_qos; + DDS_Publisher chatPublisher; + //LargeMsg_NameServiceDataWriter nameServer; + char *partitionName = NULL; + + DDS_Topic nameServiceTopic; + + int ownID; + + // LargeMsg_NameService ns; + + int i; + + LargeMsg_LargeMessageDataWriter talker; + LargeMsg_LargeMessage *msg; + DDS_ReturnCode_t status; + DDS_InstanceHandle_t userHandle; + char *msg_content; + + public: + void callback(); + bool init(); + bool teardown(); +}; + +bool ExamplePublisher::init() +{ + this->i = 0; + /* Create a DomainParticipantFactory and a DomainParticipant */ + /* (using Default QoS settings). */ + this->dpf = DDS_DomainParticipantFactory_get_instance(); + if (!dpf) { + printf("Creating ParticipantFactory failed!!\n"); + exit(-1); + } + printf("Created ParticipantFactory.\n"); + + this->dp = DDS_DomainParticipantFactory_create_participant ( + dpf, + domain, + DDS_PARTICIPANT_QOS_DEFAULT, + NULL, + DDS_STATUS_MASK_NONE); + if (!dp) { + printf("Creating Participant failed!!\n"); + exit(-1); + } + printf("Created Participant.\n"); + + + /* Register the required data type for LargeMessage. */ + this->chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); + if (!chatMessageTS) { + printf ("Allocating TypeSupport failed!!\n"); + exit(-1); + }; + this->chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); + status = LargeMsg_LargeMessageTypeSupport_register_type( + chatMessageTS, dp, chatMessageTypeName); + if (status != DDS_RETCODE_OK) { + printf("Registering data type failed. Status = %d\n", status); + exit(-1); + }; + printf("Registered data type.\n"); + + /*Create the LargeMessage topic */ + this->chatMessageTopic = DDS_DomainParticipant_create_topic( + dp, + "LargeMsg_LargeMessage", + chatMessageTypeName, + DDS_TOPIC_QOS_DEFAULT, + NULL, + DDS_STATUS_MASK_NONE); + if (!chatMessageTopic) { + printf("Creating LargeMessage topic failed!!\n"); + exit(-1); + }; + printf("Created LargeMessage topic.\n"); + + /* Adapt the default PublisherQos to write into the + "LargeMessageRoom" Partition. */ + + /*this->partitionName = "LargeMessageRoom"; + pub_qos = DDS_PublisherQos__alloc(); + if (!pub_qos) { + printf("Allocating PublisherQos failed!!\n"); + exit(-1); + } + status = DDS_DomainParticipant_get_default_publisher_qos ( + dp, pub_qos); + if (status != DDS_RETCODE_OK) { + printf("Getting default publisher qos failed!!\n"); + exit(-1); + } + pub_qos->partition.name._length = 1; + pub_qos->partition.name._maximum = 1; + pub_qos->partition.name._buffer = DDS_StringSeq_allocbuf (1); + if (!pub_qos->partition.name._buffer) { + printf("Allocating partition name failed!!\n"); + exit(-1); + } + pub_qos->partition.name._buffer[0] = DDS_string_alloc ( + strlen(partitionName)); + if (!pub_qos->partition.name._buffer[0]) { + printf("Allocating partition name failed!!\n"); + exit(-1); + } + strcpy (pub_qos->partition.name._buffer[0], partitionName); + */ + + /* Create a Publisher for the chatter application. */ + this->chatPublisher = DDS_DomainParticipant_create_publisher( + dp, pub_qos, NULL, DDS_STATUS_MASK_NONE); + if (!chatPublisher) { + printf("Creating publisher failed!!\n"); + exit(-1); + } + printf("Created publisher.\n"); + + /* Create a DataWriter for the LargeMessage Topic + (using the appropriate QoS). */ + this->talker = DDS_Publisher_create_datawriter( + chatPublisher, + chatMessageTopic, + DDS_DATAWRITER_QOS_USE_TOPIC_QOS, + NULL, + DDS_STATUS_MASK_NONE); + if (!talker) { + printf("Creating datawriter failed!!\n"); + exit(-1); + } + printf("Created datawriter.\n"); + + this->ownID = 0; + + // TODO chat message should become LargeMessage + this->msg = LargeMsg_LargeMessage__alloc(); + //checkHandle(msg, "LargeMsg_LargeMessage__alloc"); + msg->seq = 0; + msg->content = DDS_string_alloc(MAX_MSG_LEN); + //checkHandle(msg->content, "DDS_string_alloc"); + //snprintf(msg->content, MAX_MSG_LEN, "hello world"); + snprintf(msg->content, MAX_MSG_LEN, this->msg_content, msg->seq); + + // register a chat message + this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); + + //this->ns.userID = ownID; + //ns.name = DDS_string_alloc(LargeMsg_MAX_NAME+1); + //checkHandle(ns.name, "DDS_string_alloc"); + char *chatterName; + // snprintf(ns.name, LargeMsg_MAX_NAME+1, "LargeMessage %d", ownID); + + int j; + this->msg_content = (char*) malloc(MAX_MSG_LEN); + for (j < 0; j < MAX_MSG_LEN; ++j) + { + msg_content[j] = '.'; + } + + // Write user information + //status = LargeMsg_NameServiceDataWriter_write(nameServer, &ns, DDS_HANDLE_NIL); + //checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); + + printf("Created user handle and preallocated message.\n"); + + return true; +} + +void ExamplePublisher::callback() +{ + this->msg->seq = this->i; + status = LargeMsg_LargeMessageDataWriter_write(talker, msg, userHandle); + // checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); + ++i; +} + + +bool ExamplePublisher::teardown() +{ + /* Remove the DataWriters */ + status = DDS_Publisher_delete_datawriter(this->chatPublisher, + this->talker); + if (status != DDS_RETCODE_OK) { + printf("Deleting datawriter failed!!\n"); + exit(-1); + } + printf("Deleted datawriter.\n"); + + /* Remove the Publisher. */ + status = DDS_DomainParticipant_delete_publisher( + this->dp, this->chatPublisher); + if (status != DDS_RETCODE_OK) { + printf("Deleting publisher failed!!\n"); + exit(-1); + } + /* De-allocate the PublisherQoS holder. */ + DDS_free(this->pub_qos); // Note that DDS_free recursively + // de-allocates all indirections!! + printf("Deleted publisher.\n"); + + /* Deleting the Topic. */ + status = DDS_DomainParticipant_delete_topic( + dp, chatMessageTopic); + if (status != DDS_RETCODE_OK) { + printf("Deleting topic failed. Status = %d\n", status); + exit(-1); + }; + printf("Deleted LargeMessage topic.\n"); + + /* Deleting the DomainParticipant */ + status = DDS_DomainParticipantFactory_delete_participant( + this->dpf, this->dp); + if (status != DDS_RETCODE_OK) { + printf("Deleting participant failed. Status = %d\n", status); + exit(-1); + } + + printf("Deleted Participant.\n"); +} diff --git a/realtime_c/ExampleSubscriber.hpp b/realtime_c/ExampleSubscriber.hpp new file mode 100644 index 0000000..a6e2134 --- /dev/null +++ b/realtime_c/ExampleSubscriber.hpp @@ -0,0 +1,159 @@ +#include "dds_dcps.h" +#include "LargeMsg.h" +//#include "check_status.h" +#include "unistd.h" + +class ExampleSubscriber +{ + + private: + + DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; + DDS_DomainParticipantFactory dpf; + DDS_DomainParticipant dp; + DDS_SubscriberQos *sub_qos; + DDS_Subscriber chatSubscriber; + LargeMsg_LargeMessageDataReader mbReader; + //char *partitionName; + DDS_ReturnCode_t status; + DDS_sequence_LargeMsg_LargeMessage *msgSeq; + DDS_SampleInfoSeq *infoSeq; + LargeMsg_LargeMessage *msg; + unsigned long received_msgs_count; + LargeMsg_LargeMessageTypeSupport chatMessageTS; + char *chatMessageTypeName; + DDS_Topic chatMessageTopic; + + public: + void callback(); + bool init(); + bool teardown(); +}; + +bool ExampleSubscriber::init() +{ + /* Create a DomainParticipantFactory and a DomainParticipant */ + /* (using Default QoS settings). */ + this->dpf = DDS_DomainParticipantFactory_get_instance(); + if (!dpf) { + printf("Creating ParticipantFactory failed!!\n"); + exit(-1); + } + printf("Created ParticipantFactory.\n"); + + this->dp = DDS_DomainParticipantFactory_create_participant ( + dpf, + domain, + DDS_PARTICIPANT_QOS_DEFAULT, + NULL, + DDS_STATUS_MASK_NONE); + if (!dp) { + printf("Creating Participant failed!!\n"); + exit(-1); + } + printf("Created Participant.\n"); + + /* Register the required data type for LargeMessage. */ + this->chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); + if (!chatMessageTS) { + printf ("Allocating TypeSupport failed!!\n"); + exit(-1); + }; + this->chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); + status = LargeMsg_LargeMessageTypeSupport_register_type( + chatMessageTS, dp, chatMessageTypeName); + if (status != DDS_RETCODE_OK) { + printf("Registering data type failed. Status = %d\n", status); + exit(-1); + }; + printf("Registered data type.\n"); + /*Create the LargeMessage topic */ + this->chatMessageTopic = DDS_DomainParticipant_create_topic( + dp, + "LargeMsg_LargeMessage", + chatMessageTypeName, + DDS_TOPIC_QOS_DEFAULT, + NULL, + DDS_STATUS_MASK_NONE); + if (!chatMessageTopic) { + printf("Creating LargeMessage topic failed!!\n"); + exit(-1); + }; + + printf("Created LargeMessage topic.\n"); + + + /* Adapt the default SubscriberQos to read from the + "ChatRoom" Partition. */ + //this->partitionName = "ChatRoom"; + this->sub_qos = DDS_SubscriberQos__alloc(); + // checkHandle(sub_qos, "DDS_SubscriberQos__alloc"); + status = DDS_DomainParticipant_get_default_subscriber_qos(this->dp, sub_qos); + // checkStatus(status, "DDS_DomainParticipant_get_default_subscriber_qos"); + /*sub_qos->partition.name._length = 1; + sub_qos->partition.name._maximum = 1; + sub_qos->partition.name._buffer = DDS_StringSeq_allocbuf (1); + checkHandle(sub_qos->partition.name._buffer, "DDS_StringSeq_allocbuf"); + sub_qos->partition.name._buffer[0] = + DDS_string_alloc (strlen(partitionName)); + checkHandle(sub_qos->partition.name._buffer[0], "DDS_string_alloc"); + strcpy(sub_qos->partition.name._buffer[0], partitionName);*/ + /* Create a Subscriber for the MessageBoard application. */ + chatSubscriber = DDS_DomainParticipant_create_subscriber( + this->dp, sub_qos, NULL, DDS_STATUS_MASK_NONE); + // checkHandle(chatSubscriber, "DDS_DomainParticipant_create_subscriber"); + /* Create a DataReader for the ChatMessage Topic + (using the appropriate QoS). */ + this->mbReader = DDS_Subscriber_create_datareader( + chatSubscriber, + chatMessageTopic, + DDS_DATAREADER_QOS_USE_TOPIC_QOS, + NULL, + DDS_STATUS_MASK_NONE); + // checkHandle(mbReader, "DDS_Subscriber_create_datareader"); + + msgSeq = DDS_sequence_LargeMsg_LargeMessage__alloc(); + // checkHandle(msgSeq, "DDS_sequence_Chat_NamedMessage__alloc"); + infoSeq = DDS_SampleInfoSeq__alloc(); + // checkHandle(infoSeq, "DDS_SampleInfoSeq__alloc"); + received_msgs_count = 0; + + return true; +} + +void ExampleSubscriber::callback() +{ + status = LargeMsg_LargeMessageDataReader_take( + mbReader, + msgSeq, + infoSeq, + DDS_LENGTH_UNLIMITED, + DDS_ANY_SAMPLE_STATE, + DDS_ANY_VIEW_STATE, + DDS_ALIVE_INSTANCE_STATE); + // checkStatus(status, "Chat_NamedMessageDataReader_take"); + + DDS_unsigned_long i; + for (i = 0; i < msgSeq->_length; i++) { + msg = &(msgSeq->_buffer[i]); + ++this->received_msgs_count; + } + + status = LargeMsg_LargeMessageDataReader_return_loan(mbReader, msgSeq, infoSeq); + // checkStatus(status, "LargeMsg_LargeMessageDataReader_return_loan"); +} + +bool ExampleSubscriber::teardown() +{ + /* Remove the DataReader */ + DDS_Subscriber_delete_datareader(this->chatSubscriber, this->mbReader); + // checkStatus(status, "DDS_Subscriber_delete_datareader"); + /* Remove the Subscriber. */ + status = DDS_DomainParticipant_delete_subscriber(this->dp, chatSubscriber); + // checkStatus(status, "DDS_DomainParticipant_delete_subscriber"); + /* De-allocate the SubscriberQoS holder. */ + DDS_free(this->sub_qos); // Note that DDS_free recursively + // de-allocates all indirections!! + printf("Received %lu total messages.", this->received_msgs_count); + return false; +} diff --git a/realtime_c/LargeMsg.idl b/realtime_c/LargeMsg.idl new file mode 100644 index 0000000..89ece6e --- /dev/null +++ b/realtime_c/LargeMsg.idl @@ -0,0 +1,7 @@ +module LargeMsg { + struct LargeMessage { + long seq; // Message sequence number + string content; // message body + }; +#pragma keylist LargeMessage seq +}; diff --git a/realtime_c/rt_publisher.cpp b/realtime_c/rt_publisher.cpp new file mode 100644 index 0000000..061a050 --- /dev/null +++ b/realtime_c/rt_publisher.cpp @@ -0,0 +1,29 @@ +#include +#include "ExamplePublisher.hpp" + +#define STACK_SIZE 1024*1024*1024 + +ExamplePublisher pub; + +void* pub_callback(void * unused) +{ + pub.callback(); +} + +int main(int argc, char *argv[]) +{ + pub.init(); + + rttest_read_args(argc, argv); + rttest_set_sched_priority(90, SCHED_RR); + //rttest_lock_memory(); + //rttest_prefault_stack_size(STACK_SIZE); + //rttest_lock_and_prefault_dynamic(STACK_SIZE); + + rttest_spin(pub_callback, NULL); + + rttest_write_results(); + rttest_finish(); + + pub.teardown(); +} diff --git a/realtime_c/rt_subscriber.cpp b/realtime_c/rt_subscriber.cpp new file mode 100644 index 0000000..90637c2 --- /dev/null +++ b/realtime_c/rt_subscriber.cpp @@ -0,0 +1,29 @@ +#include +#include "ExampleSubscriber.hpp" + +#define STACK_SIZE 1024*1024*1024 + +ExampleSubscriber sub; + +void* sub_callback(void * unused) +{ + sub.callback(); +} + +int main(int argc, char *argv[]) +{ + sub.init(); + + rttest_read_args(argc, argv); + rttest_set_sched_priority(90, SCHED_RR); + //rttest_lock_memory(); + //rttest_prefault_stack_size(STACK_SIZE); + rttest_lock_and_prefault_dynamic(STACK_SIZE); + + rttest_spin(sub_callback, NULL); + + rttest_write_results(); + rttest_finish(); + + sub.teardown(); +} From 0e03fd39a07b1cd603d1c80d2b16173c07a1df08 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Mon, 6 Jul 2015 16:28:08 -0700 Subject: [PATCH 18/34] add subscriber --- realtime_c/ExampleSubscriber.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/realtime_c/ExampleSubscriber.hpp b/realtime_c/ExampleSubscriber.hpp index a6e2134..b35c803 100644 --- a/realtime_c/ExampleSubscriber.hpp +++ b/realtime_c/ExampleSubscriber.hpp @@ -154,6 +154,6 @@ bool ExampleSubscriber::teardown() /* De-allocate the SubscriberQoS holder. */ DDS_free(this->sub_qos); // Note that DDS_free recursively // de-allocates all indirections!! - printf("Received %lu total messages.", this->received_msgs_count); + printf("Received %lu total messages.\n", this->received_msgs_count); return false; } From 2970adbfe837d94037d0e7a69d720a3c515defe7 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Mon, 6 Jul 2015 16:29:14 -0700 Subject: [PATCH 19/34] Add build script --- realtime_c/build.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 realtime_c/build.sh diff --git a/realtime_c/build.sh b/realtime_c/build.sh new file mode 100755 index 0000000..a6d3ddf --- /dev/null +++ b/realtime_c/build.sh @@ -0,0 +1,13 @@ +rm -fr c +mkdir c +cd c +OSPL_TMPL_PATH=/usr/etc/opensplice/idlpp idlpp -S -l c ../LargeMsg.idl +echo "Generated C code under '`pwd`'" +cd .. + +rm -fr build +mkdir build +cd build +cmake .. -DCMAKE_INSTALL_PREFIX=~/local +make +cd .. From 2190608f9f76fa9070fbad55107d5a12cc28ff1f Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Mon, 6 Jul 2015 16:29:53 -0700 Subject: [PATCH 20/34] add check status --- realtime_c/check_status.h | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 realtime_c/check_status.h diff --git a/realtime_c/check_status.h b/realtime_c/check_status.h new file mode 100644 index 0000000..eefab3d --- /dev/null +++ b/realtime_c/check_status.h @@ -0,0 +1,46 @@ +#ifndef __CHECKSTATUS_H__ +#define __CHECKSTATUS_H__ + +#include "ccpp_dds_dcps.h" +#include + +const char *RetCodeName[13] = { + "DDS_RETCODE_OK", + "DDS_RETCODE_ERROR", + "DDS_RETCODE_UNSUPPORTED", + "DDS_RETCODE_BAD_PARAMETER", + "DDS_RETCODE_PRECONDITION_NOT_MET", + "DDS_RETCODE_OUT_OF_RESOURCES", + "DDS_RETCODE_NOT_ENABLED", + "DDS_RETCODE_IMMUTABLE_POLICY", + "DDS_RETCODE_INCONSISTENT_POLICY", + "DDS_RETCODE_ALREADY_DELETED", + "DDS_RETCODE_TIMEOUT", + "DDS_RETCODE_NO_DATA", + "DDS_RETCODE_ILLEGAL_OPERATION" +}; + +const char * getErrorName(DDS::ReturnCode_t status) +{ + return RetCodeName[status]; +} + +void checkStatus(DDS::ReturnCode_t status, const char *info) +{ + if (status != DDS::RETCODE_OK && status != DDS::RETCODE_NO_DATA) + { + std::cerr << "Error in " << info << ": " << getErrorName(status) << std::endl; + //exit (1); + } +} + +void checkHandle(void *handle, const char *info) +{ + if (!handle) + { + std::cerr << "Error in " << info << ": Creation failed: invalid handle" << std::endl; + exit (1); + } +} + +#endif From 765ff77ff33ef01bfb75f0404a00cd3558f64d0b Mon Sep 17 00:00:00 2001 From: Jackie Date: Mon, 6 Jul 2015 18:43:38 -0700 Subject: [PATCH 21/34] searching for error in publisher --- realtime_c/CMakeLists.txt | 10 +++ realtime_c/ExamplePublisher.hpp | 70 ++++++++---------- realtime_c/ExampleSubscriber.hpp | 42 ++++++----- realtime_c/rt_intraproc.cpp | 117 +++++++++++++++++++++++++++++++ realtime_c/rt_publisher.cpp | 36 +++++++++- realtime_c/rt_subscriber.cpp | 8 ++- 6 files changed, 216 insertions(+), 67 deletions(-) create mode 100644 realtime_c/rt_intraproc.cpp diff --git a/realtime_c/CMakeLists.txt b/realtime_c/CMakeLists.txt index 57110f4..51234eb 100644 --- a/realtime_c/CMakeLists.txt +++ b/realtime_c/CMakeLists.txt @@ -1,10 +1,13 @@ cmake_minimum_required(VERSION 2.8) project(realtime_c) +set (CMAKE_CXX_FLAGS "-std=c++11") find_package(rttest REQUIRED) find_package(opensplice REQUIRED) +find_package(Threads) + # find_package only exposes the c++ include directories but not the c headers include_directories(c /usr/include/opensplice/dcps/C/SAC ${OPENSPLICE_INCLUDE_DIRS} ${rttest_INCLUDE_DIRS}) link_directories(${OPENSPLICE_LIBRARY_DIRS} ${rttest_LIBRARY_DIR}) @@ -17,5 +20,12 @@ target_link_libraries(publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m st add_executable(subscriber rt_subscriber.cpp ${MSG_C_FILES}) target_link_libraries(subscriber ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) +if(NOT Threads_FOUND) + message(WARNING "pthread not found. Real-time intra-process pub/sub example will not be built.") +elseif(Threads_FOUND) + add_executable(intraproc rt_intraproc.cpp ${MSG_C_FILES}) + target_link_libraries(intraproc ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} m stdc++) +endif() + #add_executable(intraproc rt_intraproc.cpp ${MSG_C_FILES}) #target_link_libraries(intraproc ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) diff --git a/realtime_c/ExamplePublisher.hpp b/realtime_c/ExamplePublisher.hpp index 840f261..3bcb42d 100644 --- a/realtime_c/ExamplePublisher.hpp +++ b/realtime_c/ExamplePublisher.hpp @@ -11,32 +11,19 @@ class ExamplePublisher private: DDS_DomainParticipantFactory dpf; DDS_DomainParticipant dp; - DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; - LargeMsg_LargeMessageTypeSupport chatMessageTS; - DDS_Topic chatMessageTopic; - char *chatMessageTypeName; - DDS_PublisherQos *pub_qos; DDS_DataWriterQos *dw_qos; DDS_Publisher chatPublisher; - //LargeMsg_NameServiceDataWriter nameServer; - char *partitionName = NULL; - - DDS_Topic nameServiceTopic; - - int ownID; - - // LargeMsg_NameService ns; - - int i; - + DDS_Topic chatMessageTopic; LargeMsg_LargeMessageDataWriter talker; LargeMsg_LargeMessage *msg; DDS_ReturnCode_t status; DDS_InstanceHandle_t userHandle; - char *msg_content; + + int i; public: + unsigned int message_size; void callback(); bool init(); bool teardown(); @@ -44,6 +31,18 @@ class ExamplePublisher bool ExamplePublisher::init() { + if (message_size > MAX_MSG_LEN) + { + std::cout << "Clamping message size to maximum" << std::endl; + message_size = MAX_MSG_LEN; + } + if (message_size == 0) + { + std::cout << "Cannot have 0 message size, clamping to 1" << std::endl; + message_size = 1; + } + + DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; this->i = 0; /* Create a DomainParticipantFactory and a DomainParticipant */ /* (using Default QoS settings). */ @@ -68,12 +67,12 @@ bool ExamplePublisher::init() /* Register the required data type for LargeMessage. */ - this->chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); + LargeMsg_LargeMessageTypeSupport chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); if (!chatMessageTS) { printf ("Allocating TypeSupport failed!!\n"); exit(-1); }; - this->chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); + char *chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); status = LargeMsg_LargeMessageTypeSupport_register_type( chatMessageTS, dp, chatMessageTypeName); if (status != DDS_RETCODE_OK) { @@ -99,7 +98,7 @@ bool ExamplePublisher::init() /* Adapt the default PublisherQos to write into the "LargeMessageRoom" Partition. */ - /*this->partitionName = "LargeMessageRoom"; + const char *partitionName = "chatter"; pub_qos = DDS_PublisherQos__alloc(); if (!pub_qos) { printf("Allocating PublisherQos failed!!\n"); @@ -125,7 +124,6 @@ bool ExamplePublisher::init() exit(-1); } strcpy (pub_qos->partition.name._buffer[0], partitionName); - */ /* Create a Publisher for the chatter application. */ this->chatPublisher = DDS_DomainParticipant_create_publisher( @@ -150,36 +148,24 @@ bool ExamplePublisher::init() } printf("Created datawriter.\n"); - this->ownID = 0; + int ownID = 0; - // TODO chat message should become LargeMessage this->msg = LargeMsg_LargeMessage__alloc(); - //checkHandle(msg, "LargeMsg_LargeMessage__alloc"); msg->seq = 0; msg->content = DDS_string_alloc(MAX_MSG_LEN); - //checkHandle(msg->content, "DDS_string_alloc"); - //snprintf(msg->content, MAX_MSG_LEN, "hello world"); - snprintf(msg->content, MAX_MSG_LEN, this->msg_content, msg->seq); - - // register a chat message - this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); - - //this->ns.userID = ownID; - //ns.name = DDS_string_alloc(LargeMsg_MAX_NAME+1); - //checkHandle(ns.name, "DDS_string_alloc"); - char *chatterName; - // snprintf(ns.name, LargeMsg_MAX_NAME+1, "LargeMessage %d", ownID); int j; - this->msg_content = (char*) malloc(MAX_MSG_LEN); - for (j < 0; j < MAX_MSG_LEN; ++j) + const unsigned int message_size_const = message_size; + char msg_content[message_size_const]; + for (j < 0; j < message_size_const; ++j) { msg_content[j] = '.'; } + snprintf(msg->content, message_size_const, msg_content, msg->seq); + + // register a chat message + this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); - // Write user information - //status = LargeMsg_NameServiceDataWriter_write(nameServer, &ns, DDS_HANDLE_NIL); - //checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); printf("Created user handle and preallocated message.\n"); @@ -190,7 +176,7 @@ void ExamplePublisher::callback() { this->msg->seq = this->i; status = LargeMsg_LargeMessageDataWriter_write(talker, msg, userHandle); - // checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); + checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); ++i; } diff --git a/realtime_c/ExampleSubscriber.hpp b/realtime_c/ExampleSubscriber.hpp index b35c803..cbac4af 100644 --- a/realtime_c/ExampleSubscriber.hpp +++ b/realtime_c/ExampleSubscriber.hpp @@ -1,6 +1,6 @@ #include "dds_dcps.h" #include "LargeMsg.h" -//#include "check_status.h" +#include "check_status.h" #include "unistd.h" class ExampleSubscriber @@ -8,21 +8,18 @@ class ExampleSubscriber private: - DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; DDS_DomainParticipantFactory dpf; DDS_DomainParticipant dp; DDS_SubscriberQos *sub_qos; DDS_Subscriber chatSubscriber; LargeMsg_LargeMessageDataReader mbReader; - //char *partitionName; DDS_ReturnCode_t status; + DDS_sequence_LargeMsg_LargeMessage *msgSeq; DDS_SampleInfoSeq *infoSeq; LargeMsg_LargeMessage *msg; + unsigned long received_msgs_count; - LargeMsg_LargeMessageTypeSupport chatMessageTS; - char *chatMessageTypeName; - DDS_Topic chatMessageTopic; public: void callback(); @@ -32,6 +29,7 @@ class ExampleSubscriber bool ExampleSubscriber::init() { + DDS_DomainId_t domain = DDS_DOMAIN_ID_DEFAULT; /* Create a DomainParticipantFactory and a DomainParticipant */ /* (using Default QoS settings). */ this->dpf = DDS_DomainParticipantFactory_get_instance(); @@ -54,12 +52,12 @@ bool ExampleSubscriber::init() printf("Created Participant.\n"); /* Register the required data type for LargeMessage. */ - this->chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); + LargeMsg_LargeMessageTypeSupport chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); if (!chatMessageTS) { printf ("Allocating TypeSupport failed!!\n"); exit(-1); }; - this->chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); + char *chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); status = LargeMsg_LargeMessageTypeSupport_register_type( chatMessageTS, dp, chatMessageTypeName); if (status != DDS_RETCODE_OK) { @@ -68,7 +66,7 @@ bool ExampleSubscriber::init() }; printf("Registered data type.\n"); /*Create the LargeMessage topic */ - this->chatMessageTopic = DDS_DomainParticipant_create_topic( + DDS_Topic chatMessageTopic = DDS_DomainParticipant_create_topic( dp, "LargeMsg_LargeMessage", chatMessageTypeName, @@ -85,23 +83,23 @@ bool ExampleSubscriber::init() /* Adapt the default SubscriberQos to read from the "ChatRoom" Partition. */ - //this->partitionName = "ChatRoom"; + const char *partitionName = "chatter"; this->sub_qos = DDS_SubscriberQos__alloc(); - // checkHandle(sub_qos, "DDS_SubscriberQos__alloc"); + checkHandle(sub_qos, "DDS_SubscriberQos__alloc"); status = DDS_DomainParticipant_get_default_subscriber_qos(this->dp, sub_qos); - // checkStatus(status, "DDS_DomainParticipant_get_default_subscriber_qos"); - /*sub_qos->partition.name._length = 1; + checkStatus(status, "DDS_DomainParticipant_get_default_subscriber_qos"); + sub_qos->partition.name._length = 1; sub_qos->partition.name._maximum = 1; sub_qos->partition.name._buffer = DDS_StringSeq_allocbuf (1); checkHandle(sub_qos->partition.name._buffer, "DDS_StringSeq_allocbuf"); sub_qos->partition.name._buffer[0] = DDS_string_alloc (strlen(partitionName)); checkHandle(sub_qos->partition.name._buffer[0], "DDS_string_alloc"); - strcpy(sub_qos->partition.name._buffer[0], partitionName);*/ + strcpy(sub_qos->partition.name._buffer[0], partitionName); /* Create a Subscriber for the MessageBoard application. */ chatSubscriber = DDS_DomainParticipant_create_subscriber( this->dp, sub_qos, NULL, DDS_STATUS_MASK_NONE); - // checkHandle(chatSubscriber, "DDS_DomainParticipant_create_subscriber"); + checkHandle(chatSubscriber, "DDS_DomainParticipant_create_subscriber"); /* Create a DataReader for the ChatMessage Topic (using the appropriate QoS). */ this->mbReader = DDS_Subscriber_create_datareader( @@ -110,12 +108,12 @@ bool ExampleSubscriber::init() DDS_DATAREADER_QOS_USE_TOPIC_QOS, NULL, DDS_STATUS_MASK_NONE); - // checkHandle(mbReader, "DDS_Subscriber_create_datareader"); + checkHandle(mbReader, "DDS_Subscriber_create_datareader"); msgSeq = DDS_sequence_LargeMsg_LargeMessage__alloc(); - // checkHandle(msgSeq, "DDS_sequence_Chat_NamedMessage__alloc"); + checkHandle(msgSeq, "DDS_sequence_Chat_NamedMessage__alloc"); infoSeq = DDS_SampleInfoSeq__alloc(); - // checkHandle(infoSeq, "DDS_SampleInfoSeq__alloc"); + checkHandle(infoSeq, "DDS_SampleInfoSeq__alloc"); received_msgs_count = 0; return true; @@ -131,7 +129,7 @@ void ExampleSubscriber::callback() DDS_ANY_SAMPLE_STATE, DDS_ANY_VIEW_STATE, DDS_ALIVE_INSTANCE_STATE); - // checkStatus(status, "Chat_NamedMessageDataReader_take"); + checkStatus(status, "Chat_NamedMessageDataReader_take"); DDS_unsigned_long i; for (i = 0; i < msgSeq->_length; i++) { @@ -140,17 +138,17 @@ void ExampleSubscriber::callback() } status = LargeMsg_LargeMessageDataReader_return_loan(mbReader, msgSeq, infoSeq); - // checkStatus(status, "LargeMsg_LargeMessageDataReader_return_loan"); + checkStatus(status, "LargeMsg_LargeMessageDataReader_return_loan"); } bool ExampleSubscriber::teardown() { /* Remove the DataReader */ DDS_Subscriber_delete_datareader(this->chatSubscriber, this->mbReader); - // checkStatus(status, "DDS_Subscriber_delete_datareader"); + checkStatus(status, "DDS_Subscriber_delete_datareader"); /* Remove the Subscriber. */ status = DDS_DomainParticipant_delete_subscriber(this->dp, chatSubscriber); - // checkStatus(status, "DDS_DomainParticipant_delete_subscriber"); + checkStatus(status, "DDS_DomainParticipant_delete_subscriber"); /* De-allocate the SubscriberQoS holder. */ DDS_free(this->sub_qos); // Note that DDS_free recursively // de-allocates all indirections!! diff --git a/realtime_c/rt_intraproc.cpp b/realtime_c/rt_intraproc.cpp new file mode 100644 index 0000000..0a1b864 --- /dev/null +++ b/realtime_c/rt_intraproc.cpp @@ -0,0 +1,117 @@ +#include + +#include "ExampleSubscriber.hpp" +#include "ExamplePublisher.hpp" + +ExamplePublisher *pub; +ExampleSubscriber *sub; +unsigned int message_length; + +static void start_rt_thread(void *(*f)(void*)) +{ + pthread_t thread; + pthread_attr_t attr; + + /* init to default values */ + if (pthread_attr_init(&attr)) + { + fprintf(stderr, "Couldn't initialize pthread to default value"); + exit(1); + } + + /* Set the requested stacksize for this thread */ + // put this in rttest? + if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 2*message_length + sizeof(*sub))) + { + fprintf(stderr, "Couldn't set requested stack size for pthread"); + exit(1); + } + + /* And finally start the actual thread */ + pthread_create(&thread, &attr, f, NULL); +} + +void* pub_callback(void * unused) +{ + if (pub != NULL) + pub->callback(); +} + +void* sub_callback(void * unused) +{ + if (sub != NULL) + sub->callback(); +} + +void *publisher_thread(void *unused) +{ + rttest_spin(pub_callback, NULL); + + rttest_write_results_file("rttest_publisher_results"); + if (pub != NULL) + pub->teardown(); + rttest_finish(); +} + +void *subscriber_thread(void *unused) +{ + rttest_init_new_thread(); + rttest_set_sched_priority(98, SCHED_RR); + + rttest_spin(sub_callback, NULL); + + rttest_write_results_file("rttest_subscriber_results"); + if (sub != NULL) + sub->teardown(); + rttest_finish(); +} + +int main(int argc, char *argv[]) +{ + int c; + + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } + + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) + { + switch(c) + { + case 'l': + message_length = std::stoul(std::string(optarg)); + break; + default: + break; + } + } + rttest_read_args(argc, argv); + + pub = new ExamplePublisher(); + pub->message_size = message_length; + pub->init(); + sub = new ExampleSubscriber(); + sub->init(); + //size_t stack_size = message_length*2 + sizeof(*pub) + sizeof(*sub); + //size_t pool_size = 2*message_length; + + if (rttest_lock_memory() != 0) + { + perror("Failed to lock dynamic memory. Process might not be real-time safe"); + } + //rttest_prefault_stack_size(stack_size); + + start_rt_thread(&subscriber_thread); + + rttest_set_sched_priority(98, SCHED_RR); + + publisher_thread(NULL); +} diff --git a/realtime_c/rt_publisher.cpp b/realtime_c/rt_publisher.cpp index 061a050..7776c89 100644 --- a/realtime_c/rt_publisher.cpp +++ b/realtime_c/rt_publisher.cpp @@ -1,3 +1,5 @@ +#include + #include #include "ExamplePublisher.hpp" @@ -12,11 +14,43 @@ void* pub_callback(void * unused) int main(int argc, char *argv[]) { + unsigned int message_size = 1; + { + int c; + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } + + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) + { + switch(c) + { + case 'l': + message_size = std::stoul(std::string(optarg)); + break; + default: + break; + } + } + } + pub.message_size = message_size; pub.init(); rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); - //rttest_lock_memory(); + //getchar(); + if (rttest_lock_memory() != 0) + { + perror("Failed to lock memory"); + } //rttest_prefault_stack_size(STACK_SIZE); //rttest_lock_and_prefault_dynamic(STACK_SIZE); diff --git a/realtime_c/rt_subscriber.cpp b/realtime_c/rt_subscriber.cpp index 90637c2..cd8b6e0 100644 --- a/realtime_c/rt_subscriber.cpp +++ b/realtime_c/rt_subscriber.cpp @@ -16,9 +16,13 @@ int main(int argc, char *argv[]) rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); - //rttest_lock_memory(); + + if (rttest_lock_memory() != 0) + { + perror("Failed to lock memory"); + } + //rttest_prefault_stack_size(STACK_SIZE); - rttest_lock_and_prefault_dynamic(STACK_SIZE); rttest_spin(sub_callback, NULL); From 16d52ffada4e6369cb7f7a11df0016dd4c0e4d4a Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Tue, 7 Jul 2015 09:43:52 -0700 Subject: [PATCH 22/34] topic reliability --- realtime_c/ExampleSubscriber.hpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/realtime_c/ExampleSubscriber.hpp b/realtime_c/ExampleSubscriber.hpp index b35c803..27cfbc3 100644 --- a/realtime_c/ExampleSubscriber.hpp +++ b/realtime_c/ExampleSubscriber.hpp @@ -1,6 +1,6 @@ #include "dds_dcps.h" #include "LargeMsg.h" -//#include "check_status.h" +#include "check_status.h" #include "unistd.h" class ExampleSubscriber @@ -67,6 +67,18 @@ bool ExampleSubscriber::init() exit(-1); }; printf("Registered data type.\n"); + + /* Set QoS policty to BEST_EFFORT */ + DDS_TopicQos *topic_qos = DDS_TopicQos__alloc(); + status = DDS_DomainParticipant_get_default_topic_qos(dp, topic_qos); + checkStatus(status, "DDS_DomainParticipant_get_default_topic_qos"); + topic_qos->reliability.kind = DDS_BEST_EFFORT_RELIABILITY_QOS; + + /* Make the tailored QoS the new default. */ + status = DDS_DomainParticipant_set_default_topic_qos(participant, + topic_qos); + checkStatus(status, "DDS_DomainParticipant_set_default_topic_qos"); + /*Create the LargeMessage topic */ this->chatMessageTopic = DDS_DomainParticipant_create_topic( dp, From f3dd5a920e0b1ba51d3e46079489988edf69edea Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Tue, 7 Jul 2015 10:22:44 -0700 Subject: [PATCH 23/34] user handle --- realtime_c/ExamplePublisher.hpp | 46 +++++++++++++++++++++----------- realtime_c/ExampleSubscriber.hpp | 8 +++--- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/realtime_c/ExamplePublisher.hpp b/realtime_c/ExamplePublisher.hpp index 3bcb42d..8ffd431 100644 --- a/realtime_c/ExamplePublisher.hpp +++ b/realtime_c/ExamplePublisher.hpp @@ -12,7 +12,6 @@ class ExamplePublisher DDS_DomainParticipantFactory dpf; DDS_DomainParticipant dp; DDS_PublisherQos *pub_qos; - DDS_DataWriterQos *dw_qos; DDS_Publisher chatPublisher; DDS_Topic chatMessageTopic; LargeMsg_LargeMessageDataWriter talker; @@ -71,7 +70,8 @@ bool ExamplePublisher::init() if (!chatMessageTS) { printf ("Allocating TypeSupport failed!!\n"); exit(-1); - }; + } + char *chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); status = LargeMsg_LargeMessageTypeSupport_register_type( chatMessageTS, dp, chatMessageTypeName); @@ -81,12 +81,24 @@ bool ExamplePublisher::init() }; printf("Registered data type.\n"); + /* Set QoS policty to BEST_EFFORT */ + DDS_TopicQos *topic_qos = DDS_TopicQos__alloc(); + status = DDS_DomainParticipant_get_default_topic_qos(dp, topic_qos); + checkStatus(status, "DDS_DomainParticipant_get_default_topic_qos"); + topic_qos->reliability.kind = DDS_BEST_EFFORT_RELIABILITY_QOS; + //topic_qos->reliability.kind = DDS_RELIABLE_RELIABILITY_QOS; + + /* Make the tailored QoS the new default. */ + status = DDS_DomainParticipant_set_default_topic_qos(dp, + topic_qos); + checkStatus(status, "DDS_DomainParticipant_set_default_topic_qos"); + /*Create the LargeMessage topic */ this->chatMessageTopic = DDS_DomainParticipant_create_topic( dp, "LargeMsg_LargeMessage", chatMessageTypeName, - DDS_TOPIC_QOS_DEFAULT, + topic_qos, NULL, DDS_STATUS_MASK_NONE); if (!chatMessageTopic) { @@ -117,8 +129,7 @@ bool ExamplePublisher::init() printf("Allocating partition name failed!!\n"); exit(-1); } - pub_qos->partition.name._buffer[0] = DDS_string_alloc ( - strlen(partitionName)); + pub_qos->partition.name._buffer[0] = DDS_string_alloc(strlen(partitionName)); if (!pub_qos->partition.name._buffer[0]) { printf("Allocating partition name failed!!\n"); exit(-1); @@ -146,27 +157,24 @@ bool ExamplePublisher::init() printf("Creating datawriter failed!!\n"); exit(-1); } + checkHandle(talker, "DDS_Publisher_create_datawriter"); printf("Created datawriter.\n"); int ownID = 0; this->msg = LargeMsg_LargeMessage__alloc(); + checkHandle(msg, "LargeMsg_LargeMessage__alloc"); msg->seq = 0; - msg->content = DDS_string_alloc(MAX_MSG_LEN); + //const unsigned int message_size_const = message_size; + msg->content = DDS_string_alloc(message_size); + checkHandle(msg->content, "DDS_string__alloc"); - int j; - const unsigned int message_size_const = message_size; - char msg_content[message_size_const]; - for (j < 0; j < message_size_const; ++j) - { - msg_content[j] = '.'; - } - snprintf(msg->content, message_size_const, msg_content, msg->seq); + // int j; + // snprintf(msg->content, message_size_const, msg_content, msg->seq); // register a chat message this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); - printf("Created user handle and preallocated message.\n"); return true; @@ -175,6 +183,14 @@ bool ExamplePublisher::init() void ExamplePublisher::callback() { this->msg->seq = this->i; + + int j; + for (j < 0; j < this->message_size; ++j) + { + msg->content[j] = '.'; + } + + this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); status = LargeMsg_LargeMessageDataWriter_write(talker, msg, userHandle); checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); ++i; diff --git a/realtime_c/ExampleSubscriber.hpp b/realtime_c/ExampleSubscriber.hpp index da93485..a02fffe 100644 --- a/realtime_c/ExampleSubscriber.hpp +++ b/realtime_c/ExampleSubscriber.hpp @@ -56,7 +56,8 @@ bool ExampleSubscriber::init() if (!chatMessageTS) { printf ("Allocating TypeSupport failed!!\n"); exit(-1); - }; + } + char *chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); status = LargeMsg_LargeMessageTypeSupport_register_type( chatMessageTS, dp, chatMessageTypeName); @@ -71,9 +72,10 @@ bool ExampleSubscriber::init() status = DDS_DomainParticipant_get_default_topic_qos(dp, topic_qos); checkStatus(status, "DDS_DomainParticipant_get_default_topic_qos"); topic_qos->reliability.kind = DDS_BEST_EFFORT_RELIABILITY_QOS; + //topic_qos->reliability.kind = DDS_RELIABLE_RELIABILITY_QOS; /* Make the tailored QoS the new default. */ - status = DDS_DomainParticipant_set_default_topic_qos(participant, + status = DDS_DomainParticipant_set_default_topic_qos(dp, topic_qos); checkStatus(status, "DDS_DomainParticipant_set_default_topic_qos"); @@ -82,7 +84,7 @@ bool ExampleSubscriber::init() dp, "LargeMsg_LargeMessage", chatMessageTypeName, - DDS_TOPIC_QOS_DEFAULT, + topic_qos, NULL, DDS_STATUS_MASK_NONE); if (!chatMessageTopic) { From b6be3b1c57ee1b9df13fff4081efc57f6f310ab5 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Tue, 7 Jul 2015 10:33:36 -0700 Subject: [PATCH 24/34] Try to unregister instance --- realtime_c/ExamplePublisher.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/realtime_c/ExamplePublisher.hpp b/realtime_c/ExamplePublisher.hpp index 8ffd431..06ce3f7 100644 --- a/realtime_c/ExamplePublisher.hpp +++ b/realtime_c/ExamplePublisher.hpp @@ -173,7 +173,6 @@ bool ExamplePublisher::init() // snprintf(msg->content, message_size_const, msg_content, msg->seq); // register a chat message - this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); printf("Created user handle and preallocated message.\n"); @@ -192,6 +191,7 @@ void ExamplePublisher::callback() this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); status = LargeMsg_LargeMessageDataWriter_write(talker, msg, userHandle); + LargeMsg_LargeMessageDataWriter_unregister_instance(talker, msg, this->userHandle ); checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); ++i; } From 03baa9045819a1d0767710011ec6ac42bf36c09c Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 8 Jul 2015 14:36:48 -0700 Subject: [PATCH 25/34] RTI Connext intraprocess example working --- realtime_connext/CMakeLists.txt | 31 +++++++ realtime_connext/USER_QOS_PROFILES.xml | 114 +++++++++++++++++++++++++ realtime_connext/build.sh | 8 ++ realtime_connext/makefile | 76 +++++++++++++++++ realtime_connext/poll.idl | 15 ++++ realtime_connext/poll_intraproc.cxx | 42 +++++++++ realtime_connext/poll_publisher.cxx | 113 ++++++++++++++++++++++++ realtime_connext/poll_subscriber.cxx | 112 ++++++++++++++++++++++++ 8 files changed, 511 insertions(+) create mode 100644 realtime_connext/CMakeLists.txt create mode 100644 realtime_connext/USER_QOS_PROFILES.xml create mode 100644 realtime_connext/build.sh create mode 100644 realtime_connext/makefile create mode 100644 realtime_connext/poll.idl create mode 100644 realtime_connext/poll_intraproc.cxx create mode 100644 realtime_connext/poll_publisher.cxx create mode 100644 realtime_connext/poll_subscriber.cxx diff --git a/realtime_connext/CMakeLists.txt b/realtime_connext/CMakeLists.txt new file mode 100644 index 0000000..57a8d28 --- /dev/null +++ b/realtime_connext/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +project(realtime_connext) + + +find_package(nddscpp REQUIRED) +find_package(rttest REQUIRED) + +add_definitions(${nddscpp_DEFINITIONS}) + +link_directories(${rttest_LIBRARY_DIR}) +include_directories(${rttest_INCLUDE_DIRS} ${nddscpp_INCLUDE_DIRS}) + +set(CMAKE_CXX_FLAGS ${rttest_FLAGS}) + +add_library(poll_msg poll.cxx pollPlugin.cxx pollSupport.cxx) +target_link_libraries(poll_msg ${nddscpp_LIBRARIES}) + +add_executable(poll_publisher poll_publisher.cxx) +target_link_libraries(poll_publisher poll_msg ${rttest_LIBRARIES}) + +add_executable(poll_subscriber poll_subscriber.cxx) +target_link_libraries(poll_subscriber poll_msg ${rttest_LIBRARIES}) + +find_package(Threads) +if(NOT Threads_FOUND) + message(WARNING "pthread not found. Intra-process pub/sub example will not be built") +elseif (Threads_FOUND) + add_executable(poll_intraproc poll_intraproc.cxx) + target_link_libraries(poll_intraproc poll_msg ${rttest_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +endif() diff --git a/realtime_connext/USER_QOS_PROFILES.xml b/realtime_connext/USER_QOS_PROFILES.xml new file mode 100644 index 0000000..374b827 --- /dev/null +++ b/realtime_connext/USER_QOS_PROFILES.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + pollDataWriter + + + + + + + pollDataReader + + + + + + + pollParticipant + pollParticipantRole + + + + + + + diff --git a/realtime_connext/build.sh b/realtime_connext/build.sh new file mode 100644 index 0000000..484d63d --- /dev/null +++ b/realtime_connext/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rtiddsgen2 poll.idl -replace -language C++ -example x64Linux3.xgcc4.6.3 + +mkdir build +cd build +cmake .. +make diff --git a/realtime_connext/makefile b/realtime_connext/makefile new file mode 100644 index 0000000..46a812e --- /dev/null +++ b/realtime_connext/makefile @@ -0,0 +1,76 @@ +###################################################################### +# makefile_async_x64Linux3.xgcc4.6.3 +# +# (c) Copyright, Real-Time Innovations, 2012. All rights reserved. +# No duplications, whole or partial, manual or electronic, may be made +# without express written permission. Any such copies, or +# revisions thereof, must display this notice unaltered. +# This code contains trade secrets of Real-Time Innovations, Inc. +# +# +# This makefile was automatically generated by rtiddsgen. +# +# To compile, type: +# gmake -f makefile_async_x64Linux3.xgcc4.6.3 +# +# Note: This makefile is only meant to build our example applications and +# may require alterations to build on your system. +# +# This makefile assumes that your build environment is already correctly +# configured. (For example, the correct version of your compiler and +# linker should be on your PATH.) +###################################################################### + +c_cc_x64Linux3.xgcc4.6.3 = gcc +c_cc_flags_x64Linux3.xgcc4.6.3 = -m64 -Wall +c_ld_x64Linux3.xgcc4.6.3 = gcc +c_ld_flags_x64Linux3.xgcc4.6.3 = -m64 +cxx_cc_x64Linux3.xgcc4.6.3 = g++ +cxx_cc_flags_x64Linux3.xgcc4.6.3 = -m64 -Wall +cxx_ld_x64Linux3.xgcc4.6.3 = g++ +cxx_ld_flags_x64Linux3.xgcc4.6.3 = -m64 -static-libgcc +syslibs_x64Linux3.xgcc4.6.3 = -ldl -lnsl -lm -lpthread -lrt +DEFINES_ARCH_SPECIFIC = -DRTI_UNIX -DRTI_LINUX -DRTI_64BIT + + +DEFINES = $(DEFINES_ARCH_SPECIFIC) $(cxx_DEFINES_ARCH_SPECIFIC) + +INCLUDES = -I. -I$(NDDSHOME)/include -I$(NDDSHOME)/include/ndds + +LIBS = -L$(NDDSHOME)/lib/x64Linux3.xgcc4.6.3 \ + -lnddscppz -lnddscz -lnddscorez $(syslibs_x64Linux3.xgcc4.6.3) + +CDRSOURCES = async.idl +COMMONSOURCES = asyncPlugin.cxx asyncSupport.cxx async.cxx +EXEC = async_publisher async_subscriber +DIRECTORIES = objs.dir objs/x64Linux3.xgcc4.6.3.dir +COMMONOBJS = $(COMMONSOURCES:%.cxx=objs/x64Linux3.xgcc4.6.3/%.o) + +# We actually stick the objects in a sub directory to keep your directory clean. +x64Linux3.xgcc4.6.3 : $(DIRECTORIES) $(COMMONOBJS) \ + $(EXEC:%=objs/x64Linux3.xgcc4.6.3/%.o) \ + $(EXEC:%=objs/x64Linux3.xgcc4.6.3/%.out) + +objs/x64Linux3.xgcc4.6.3/%.out : objs/x64Linux3.xgcc4.6.3/%.o + $(cxx_ld_x64Linux3.xgcc4.6.3) $(cxx_ld_flags_x64Linux3.xgcc4.6.3) -o $(@:%.out=%) $(@:%.out=%.o) $(COMMONOBJS) $(LIBS) + +objs/x64Linux3.xgcc4.6.3/%.o : %.cxx + $(cxx_cc_x64Linux3.xgcc4.6.3) $(cxx_cc_flags_x64Linux3.xgcc4.6.3) -o $@ $(DEFINES) $(INCLUDES) -c $< + +# +# Uncomment these lines if you want the support files regenerated when idl +# file is modified +# +async.cxx async.h \ +asyncPlugin.cxx asyncPlugin.h \ +asyncSupport.cxx asyncSupport.h : \ + async.idl + rtiddsgen2 async.idl -replace + +# Here is how we create those subdirectories automatically. +%.dir : + @echo "Checking directory $*" + @if [ ! -d $* ]; then \ + echo "Making directory $*"; \ + mkdir -p $* ; \ + fi; diff --git a/realtime_connext/poll.idl b/realtime_connext/poll.idl new file mode 100644 index 0000000..a5be389 --- /dev/null +++ b/realtime_connext/poll.idl @@ -0,0 +1,15 @@ +/******************************************************************************* + (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved. + RTI grants Licensee a license to use, modify, compile, and create derivative + works of the Software. Licensee has the right to distribute object form only + for use with RTI products. The Software is provided "as is", with no warranty + of any type, including any warranty for fitness for any purpose. RTI is under + no obligation to maintain or support the Software. RTI shall not be liable for + any incidental or consequential damages arising out of the use or inability to + use the software. + ******************************************************************************/ +struct poll { + long seq; + string content; +}; + diff --git a/realtime_connext/poll_intraproc.cxx b/realtime_connext/poll_intraproc.cxx new file mode 100644 index 0000000..24ff8f8 --- /dev/null +++ b/realtime_connext/poll_intraproc.cxx @@ -0,0 +1,42 @@ +#include "poll_utils.cxx" + +#if !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) +int main(int argc, char *argv[]) +{ + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + Arguments args; + args.argc = argc; + args.argv = argv; + + pthread_t thread; + pthread_attr_t attr; + if (pthread_attr_init(&attr)) + { + fprintf(stderr, "Couldn't initialize pthread to default value"); + exit(1); + } + pthread_create(&thread, &attr, publisher_main, static_cast(&args)); + return subscriber_main(&args); +} +#endif + +#ifdef RTI_VX653 +const unsigned char* __ctype = *(__ctypePtrGet()); + +extern "C" void usrAppInit () +{ +#ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ +#endif + + /* add application specific code here */ + taskSpawn("pub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)publisher_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +} +#endif + diff --git a/realtime_connext/poll_publisher.cxx b/realtime_connext/poll_publisher.cxx new file mode 100644 index 0000000..9de137f --- /dev/null +++ b/realtime_connext/poll_publisher.cxx @@ -0,0 +1,113 @@ +/******************************************************************************* + (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved. + RTI grants Licensee a license to use, modify, compile, and create derivative + works of the Software. Licensee has the right to distribute object form only + for use with RTI products. The Software is provided "as is", with no warranty + of any type, including any warranty for fitness for any purpose. RTI is under + no obligation to maintain or support the Software. RTI shall not be liable for + any incidental or consequential damages arising out of the use or inability to + use the software. + ******************************************************************************/ +/* poll_publisher.cxx + + A publication of data of type poll + + This file is derived from code automatically generated by the rtiddsgen + command: + + rtiddsgen -language C++ -example poll.idl + + Example publication of type poll automatically generated by + 'rtiddsgen'. To test them follow these steps: + + (1) Compile this file and the example subscription. + + (2) Start the subscription with the command + objs//poll_subscriber + + (3) Start the publication with the command + objs//poll_publisher + + (4) [Optional] Specify the list of discovery initial peers and + multicast receive addresses via an environment variable or a file + (in the current working directory) called NDDS_DISCOVERY_PEERS. + + You can run any number of publishers and subscribers programs, and can + add and remove them dynamically from the domain. + + + Example: + + To run the example application on domain : + + On Unix: + + objs//poll_publisher o + objs//poll_subscriber + + On Windows: + + objs\\poll_publisher + objs\\poll_subscriber + + +modification history +------------ ------- +*/ + +#include +#include +#ifdef RTI_VX653 +#include +#endif +#include "poll.h" +#include "pollSupport.h" +#include "ndds/ndds_cpp.h" + +#include + +#include "poll_utils.cxx" + + +#if defined(RTI_WINCE) +int wmain(int argc, wchar_t** argv) +{ + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return publisher_main(domainId, sample_count); +} + +#elif !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) +int main(int argc, char *argv[]) +{ + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return publisher_main(argc, argv); +} +#endif + +#ifdef RTI_VX653 +const unsigned char* __ctype = *(__ctypePtrGet()); + +extern "C" void usrAppInit () +{ +#ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ +#endif + + /* add application specific code here */ + taskSpawn("pub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)publisher_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +} +#endif + diff --git a/realtime_connext/poll_subscriber.cxx b/realtime_connext/poll_subscriber.cxx new file mode 100644 index 0000000..684dee3 --- /dev/null +++ b/realtime_connext/poll_subscriber.cxx @@ -0,0 +1,112 @@ +/******************************************************************************* + (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved. + RTI grants Licensee a license to use, modify, compile, and create derivative + works of the Software. Licensee has the right to distribute object form only + for use with RTI products. The Software is provided "as is", with no warranty + of any type, including any warranty for fitness for any purpose. RTI is under + no obligation to maintain or support the Software. RTI shall not be liable for + any incidental or consequential damages arising out of the use or inability to + use the software. + ******************************************************************************/ +/* poll_subscriber.cxx + + A subscription example + + This file is derived from code automatically generated by the rtiddsgen + command: + + rtiddsgen -language C++ -example poll.idl + + Example subscription of type poll automatically generated by + 'rtiddsgen'. To test them follow these steps: + + (1) Compile this file and the example publication. + + (2) Start the subscription with the command + objs//poll_subscriber + + (3) Start the publication with the command + objs//poll_publisher + + (4) [Optional] Specify the list of discovery initial peers and + multicast receive addresses via an environment variable or a file + (in the current working directory) called NDDS_DISCOVERY_PEERS. + + You can run any number of publishers and subscribers programs, and can + add and remove them dynamically from the domain. + + + Example: + + To run the example application on domain : + + On Unix: + + objs//poll_publisher + objs//poll_subscriber + + On Windows: + + objs\\poll_publisher + objs\\poll_subscriber + + +modification history +------------ ------- +*/ + +#include +#include +#ifdef RTI_VX653 +#include +#endif +#include "poll.h" +#include "pollSupport.h" +#include "ndds/ndds_cpp.h" + +#include "poll_utils.cxx" + +#if defined(RTI_WINCE) +int wmain(int argc, wchar_t** argv) +{ + + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return subscriber_main(domainId, sample_count); +} + +#elif !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) +int main(int argc, char *argv[]) +{ + + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return subscriber_main(argc, argv); +} +#endif + +#ifdef RTI_VX653 +const unsigned char* __ctype = *(__ctypePtrGet()); + +extern "C" void usrAppInit () +{ +#ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ +#endif + + /* add application specific code here */ + taskSpawn("sub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)subscriber_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +} +#endif + From 64b66ccbf47db95e2ca17c127d7282f8f76361fe Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 8 Jul 2015 14:39:01 -0700 Subject: [PATCH 26/34] Added utils file --- realtime_connext/poll_utils.cxx | 460 ++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) create mode 100644 realtime_connext/poll_utils.cxx diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx new file mode 100644 index 0000000..cdb72f6 --- /dev/null +++ b/realtime_connext/poll_utils.cxx @@ -0,0 +1,460 @@ +#ifndef EXAMPLE_POLL_UTILS_H +#define EXAMPLE_POLL_UTILS_H + +#include +#include +#include + +#ifdef RTI_VX653 +#include +#endif +#include "poll.h" +#include "pollSupport.h" +#include "ndds/ndds_cpp.h" + +#include + +struct PublisherNode +{ + pollDataWriter * poll_writer; + poll *instance; + DDS_InstanceHandle_t instance_handle; + int count; + //std::string content; +}; + +struct Arguments +{ + int argc; + char **argv; +}; + +/* Delete all entities */ +static int subscriber_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides the finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ +/* + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + status = -1; + } +*/ + return status; +} + +void *subscriber_callback(void *args) +{ + pollDataReader *poll_reader = static_cast(args); + DDS_SampleInfoSeq info_seq; + pollSeq data_seq; + + /* Check for new data calling the DataReader's take() method */ + DDS_ReturnCode_t retcode = poll_reader->take( + data_seq, info_seq, DDS_LENGTH_UNLIMITED, + DDS_ANY_SAMPLE_STATE, DDS_ANY_VIEW_STATE, DDS_ANY_INSTANCE_STATE); + if (retcode == DDS_RETCODE_NO_DATA) { + /// Not an error + return NULL; + } else if (retcode != DDS_RETCODE_OK) { + // Is an error + printf("take error: %d\n", retcode); + exit(-1); + } + + int len = 0; + double sum = 0; + + /* Iterate through the samples read using the take() method, getting + * the number of samples got and, adding the value of x on each of + * them to calculate the average afterwards. */ + for (int i = 0; i < data_seq.length(); ++i) { + if (!info_seq[i].valid_data) + continue; + len ++; + sum += data_seq[i].seq; + } + + /* + if (len > 0) + printf("Got %d samples. Avg = %.1f\n", len, sum/len); + */ + + retcode = poll_reader->return_loan(data_seq, info_seq); + if (retcode != DDS_RETCODE_OK) { + printf("return loan error %d\n", retcode); + } + +} + +int subscriber_main(int argc, char *argv[]) +{ + rttest_read_args(argc, argv); + + int domainId = 0; + DDSDomainParticipant *participant = NULL; + DDSSubscriber *subscriber = NULL; + DDSTopic *topic = NULL; + DDSDataReader *reader = NULL; + DDS_ReturnCode_t retcode; + const char *type_name = NULL; + int count = 0; + /* Poll for new samples every 5 seconds */ + DDS_Duration_t receive_period = {5,0}; + int status = 0; + + /* To customize the participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the subscriber QoS, use + the configuration file USER_QOS_PROFILES.xml */ + subscriber = participant->create_subscriber( + DDS_SUBSCRIBER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (subscriber == NULL) { + printf("create_subscriber error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Register the type before creating the topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Call create_datareader passing NULL in the listener parameter */ + reader = subscriber->create_datareader( + topic, DDS_DATAREADER_QOS_DEFAULT, NULL, + DDS_STATUS_MASK_ALL); + if (reader == NULL) { + printf("create_datareader error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* If you want to change datareader_qos.history.kind programmatically rather + * than using the XML file, you will need to add the following lines to your + * code and comment out the create_datareader call above. */ + + /* + DDS_DataReaderQos datareader_qos; + retcode = subscriber->get_default_datareader_qos(datareader_qos); + if (retcode != DDS_RETCODE_OK) { + printf("get_default_datareader_qos error\n"); + return -1; + } + + datareader_qos.history.kind = DDS_KEEP_ALL_HISTORY_QOS; + + reader = subscriber->create_datareader( + topic, datareader_qos, NULL, + DDS_STATUS_MASK_ALL); + if (reader == NULL) { + printf("create_datareader error\n"); + subscriber_shutdown(participant); + return -1; + } + */ + + pollDataReader *poll_reader = pollDataReader::narrow(reader); + if (poll_reader == NULL) { + printf("DataReader narrow error\n"); + return -1; + } + + rttest_set_sched_priority(SCHED_RR, 97); + + if (rttest_lock_memory() != 0) { + perror("Couldn't lock memory"); + } + + /* Main loop */ + // TODO rttest_spin here + rttest_spin(subscriber_callback, static_cast(poll_reader)); + + /* Delete all entities */ + status = subscriber_shutdown(participant); + + rttest_write_results_file("rttest_subscriber_results"); + rttest_finish(); + + return status; +} + +int subscriber_main(Arguments *args) +{ + return subscriber_main(args->argc, args->argv); +} + +void *subscriber_main(void *args) +{ + Arguments *new_args = static_cast(args); + int ret = subscriber_main(new_args); + return static_cast(&ret); +} + +/* Delete all entities */ +static int publisher_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ +/* + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + status = -1; + } +*/ + + return status; +} + +void *publisher_callback(void *args) +{ + PublisherNode *pub_node = static_cast(args); + // message instance, instance_handle, poll_writer + /* TODO Modify the data to be written here */ + /* Set x to a random number between 0 and 9 */ + pub_node->instance->seq = (int)(rand()/(RAND_MAX/10.0)); + + DDS_ReturnCode_t retcode = pub_node->poll_writer->write(*pub_node->instance, pub_node->instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("write error %d\n", retcode); + } + ++pub_node->count; +} + +int publisher_main(int argc, char *argv[]) +{ + unsigned int message_length = 1; + { + int c; + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } + + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) + { + switch(c) + { + case 'l': + message_length = std::stoul(std::string(optarg)); + break; + default: + break; + } + } + } + + rttest_read_args(argc, argv); + int domainId = 0; + DDSDomainParticipant *participant = NULL; + DDSPublisher *publisher = NULL; + DDSTopic *topic = NULL; + DDSDataWriter *writer = NULL; + pollDataWriter * poll_writer = NULL; + poll *instance = NULL; + DDS_ReturnCode_t retcode; + DDS_InstanceHandle_t instance_handle = DDS_HANDLE_NIL; + const char *type_name = NULL; + int count = 0; + + /* To customize participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize publisher QoS, use + the configuration file USER_QOS_PROFILES.xml */ + publisher = participant->create_publisher( + DDS_PUBLISHER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (publisher == NULL) { + printf("create_publisher error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Register type before creating topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + publisher_shutdown(participant); + return -1; + } + + /* To customize topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize data writer QoS, use + the configuration file USER_QOS_PROFILES.xml */ + writer = publisher->create_datawriter( + topic, DDS_DATAWRITER_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (writer == NULL) { + printf("create_datawriter error\n"); + publisher_shutdown(participant); + return -1; + } + poll_writer = pollDataWriter::narrow(writer); + if (poll_writer == NULL) { + printf("DataWriter narrow error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Create data sample for writing */ + + instance = pollTypeSupport::create_data(); + + if (instance == NULL) { + printf("pollTypeSupport::create_data error\n"); + publisher_shutdown(participant); + return -1; + } + strcpy(instance->content, std::string(message_length, '.').c_str()); + + /* For a data type that has a key, if the same instance is going to be + written multiple times, initialize the key here + and register the keyed instance prior to writing */ +/* + instance_handle = poll_writer->register_instance(*instance); +*/ + PublisherNode pub_node; + pub_node.instance = instance; + pub_node.instance_handle = instance_handle; + pub_node.poll_writer = poll_writer; + pub_node.count = 0; + + /* Initialize random seed before entering the loop */ + // srand(time(NULL)); + + rttest_set_sched_priority(SCHED_RR, 98); + + if (rttest_lock_memory() != 0) { + perror("Couldn't lock memory"); + } + rttest_spin(publisher_callback, static_cast(&pub_node)); + rttest_write_results_file("rttest_publisher_results"); + rttest_finish(); + +/* + retcode = poll_writer->unregister_instance( + *instance, instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("unregister instance error %d\n", retcode); + } +*/ + + /* Delete data sample */ + retcode = pollTypeSupport::delete_data(instance); + if (retcode != DDS_RETCODE_OK) { + printf("pollTypeSupport::delete_data error %d\n", retcode); + } + + /* Delete all entities */ + return publisher_shutdown(participant); +} + +int publisher_main(Arguments *args) +{ + return publisher_main(args->argc, args->argv); +} + +void *publisher_main(void *args) +{ + Arguments *new_args = static_cast(args); + int ret = publisher_main(new_args); + return static_cast(&ret); +} + +#endif From 257f5da8c15436079faa12e6f2d1ee07866c3937 Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 8 Jul 2015 14:53:25 -0700 Subject: [PATCH 27/34] show received messages in connext subscriber --- realtime_c/ExamplePublisher.hpp | 73 ++++---- realtime_c/rt_publisher.cpp | 2 +- realtime_connext/poll_publisher.cxx | 241 ++++++++++++++++++++---- realtime_connext/poll_subscriber.cxx | 269 +++++++++++++++++++++++---- realtime_connext/poll_utils.cxx | 4 + 5 files changed, 478 insertions(+), 111 deletions(-) diff --git a/realtime_c/ExamplePublisher.hpp b/realtime_c/ExamplePublisher.hpp index 06ce3f7..9897961 100644 --- a/realtime_c/ExamplePublisher.hpp +++ b/realtime_c/ExamplePublisher.hpp @@ -11,13 +11,13 @@ class ExamplePublisher private: DDS_DomainParticipantFactory dpf; DDS_DomainParticipant dp; - DDS_PublisherQos *pub_qos; + DDS_PublisherQos pub_qos; + DDS_TopicQos topic_qos; DDS_Publisher chatPublisher; DDS_Topic chatMessageTopic; LargeMsg_LargeMessageDataWriter talker; - LargeMsg_LargeMessage *msg; + LargeMsg_LargeMessage msg; DDS_ReturnCode_t status; - DDS_InstanceHandle_t userHandle; int i; @@ -64,7 +64,6 @@ bool ExamplePublisher::init() } printf("Created Participant.\n"); - /* Register the required data type for LargeMessage. */ LargeMsg_LargeMessageTypeSupport chatMessageTS = LargeMsg_LargeMessageTypeSupport__alloc(); if (!chatMessageTS) { @@ -73,24 +72,24 @@ bool ExamplePublisher::init() } char *chatMessageTypeName = LargeMsg_LargeMessageTypeSupport_get_type_name(chatMessageTS); - status = LargeMsg_LargeMessageTypeSupport_register_type( - chatMessageTS, dp, chatMessageTypeName); + status = LargeMsg_LargeMessageTypeSupport_register_type(chatMessageTS, dp, chatMessageTypeName); if (status != DDS_RETCODE_OK) { printf("Registering data type failed. Status = %d\n", status); exit(-1); }; printf("Registered data type.\n"); + DDS_free(chatMessageTS); /* Set QoS policty to BEST_EFFORT */ - DDS_TopicQos *topic_qos = DDS_TopicQos__alloc(); - status = DDS_DomainParticipant_get_default_topic_qos(dp, topic_qos); + //topic_qos = DDS_TopicQos__alloc(); + status = DDS_DomainParticipant_get_default_topic_qos(dp, &topic_qos); checkStatus(status, "DDS_DomainParticipant_get_default_topic_qos"); - topic_qos->reliability.kind = DDS_BEST_EFFORT_RELIABILITY_QOS; + topic_qos.reliability.kind = DDS_BEST_EFFORT_RELIABILITY_QOS; //topic_qos->reliability.kind = DDS_RELIABLE_RELIABILITY_QOS; /* Make the tailored QoS the new default. */ status = DDS_DomainParticipant_set_default_topic_qos(dp, - topic_qos); + &topic_qos); checkStatus(status, "DDS_DomainParticipant_set_default_topic_qos"); /*Create the LargeMessage topic */ @@ -98,7 +97,7 @@ bool ExamplePublisher::init() dp, "LargeMsg_LargeMessage", chatMessageTypeName, - topic_qos, + &topic_qos, NULL, DDS_STATUS_MASK_NONE); if (!chatMessageTopic) { @@ -111,34 +110,37 @@ bool ExamplePublisher::init() "LargeMessageRoom" Partition. */ const char *partitionName = "chatter"; + + /* pub_qos = DDS_PublisherQos__alloc(); if (!pub_qos) { printf("Allocating PublisherQos failed!!\n"); exit(-1); - } + }*/ + status = DDS_DomainParticipant_get_default_publisher_qos ( - dp, pub_qos); + dp, &pub_qos); if (status != DDS_RETCODE_OK) { printf("Getting default publisher qos failed!!\n"); exit(-1); } - pub_qos->partition.name._length = 1; - pub_qos->partition.name._maximum = 1; - pub_qos->partition.name._buffer = DDS_StringSeq_allocbuf (1); - if (!pub_qos->partition.name._buffer) { + pub_qos.partition.name._length = 1; + pub_qos.partition.name._maximum = 1; + pub_qos.partition.name._buffer = DDS_StringSeq_allocbuf(1); + if (!pub_qos.partition.name._buffer) { printf("Allocating partition name failed!!\n"); exit(-1); } - pub_qos->partition.name._buffer[0] = DDS_string_alloc(strlen(partitionName)); - if (!pub_qos->partition.name._buffer[0]) { + pub_qos.partition.name._buffer[0] = DDS_string_alloc(strlen(partitionName)); + if (!pub_qos.partition.name._buffer[0]) { printf("Allocating partition name failed!!\n"); exit(-1); } - strcpy (pub_qos->partition.name._buffer[0], partitionName); + strcpy(pub_qos.partition.name._buffer[0], partitionName); /* Create a Publisher for the chatter application. */ this->chatPublisher = DDS_DomainParticipant_create_publisher( - dp, pub_qos, NULL, DDS_STATUS_MASK_NONE); + dp, &pub_qos, NULL, DDS_STATUS_MASK_NONE); if (!chatPublisher) { printf("Creating publisher failed!!\n"); exit(-1); @@ -162,12 +164,17 @@ bool ExamplePublisher::init() int ownID = 0; - this->msg = LargeMsg_LargeMessage__alloc(); - checkHandle(msg, "LargeMsg_LargeMessage__alloc"); - msg->seq = 0; + //this->msg = LargeMsg_LargeMessage__alloc(); + //checkHandle(msg, "LargeMsg_LargeMessage__alloc"); + msg.seq = 0; //const unsigned int message_size_const = message_size; - msg->content = DDS_string_alloc(message_size); - checkHandle(msg->content, "DDS_string__alloc"); + msg.content = DDS_string_alloc(message_size); + checkHandle(msg.content, "DDS_string__alloc"); + int j; + for (j < 0; j < this->message_size; ++j) + { + msg.content[j] = '.'; + } // int j; // snprintf(msg->content, message_size_const, msg_content, msg->seq); @@ -175,23 +182,22 @@ bool ExamplePublisher::init() // register a chat message printf("Created user handle and preallocated message.\n"); - return true; } void ExamplePublisher::callback() { - this->msg->seq = this->i; + this->msg.seq = this->i; int j; for (j < 0; j < this->message_size; ++j) { - msg->content[j] = '.'; + msg.content[j] = '.'; } - this->userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, msg); - status = LargeMsg_LargeMessageDataWriter_write(talker, msg, userHandle); - LargeMsg_LargeMessageDataWriter_unregister_instance(talker, msg, this->userHandle ); + DDS_InstanceHandle_t userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, &msg); + status = LargeMsg_LargeMessageDataWriter_write(talker, &msg, userHandle); + //LargeMsg_LargeMessageDataWriter_unregister_instance(talker, msg, userHandle ); checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); ++i; } @@ -216,7 +222,7 @@ bool ExamplePublisher::teardown() exit(-1); } /* De-allocate the PublisherQoS holder. */ - DDS_free(this->pub_qos); // Note that DDS_free recursively + //DDS_free(this->pub_qos); // Note that DDS_free recursively // de-allocates all indirections!! printf("Deleted publisher.\n"); @@ -227,6 +233,7 @@ bool ExamplePublisher::teardown() printf("Deleting topic failed. Status = %d\n", status); exit(-1); }; + //DDS_free(this->topic_qos); printf("Deleted LargeMessage topic.\n"); /* Deleting the DomainParticipant */ diff --git a/realtime_c/rt_publisher.cpp b/realtime_c/rt_publisher.cpp index 7776c89..355a8d4 100644 --- a/realtime_c/rt_publisher.cpp +++ b/realtime_c/rt_publisher.cpp @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) rttest_read_args(argc, argv); rttest_set_sched_priority(90, SCHED_RR); - //getchar(); + getchar(); if (rttest_lock_memory() != 0) { perror("Failed to lock memory"); diff --git a/realtime_connext/poll_publisher.cxx b/realtime_connext/poll_publisher.cxx index 9de137f..3e26727 100644 --- a/realtime_connext/poll_publisher.cxx +++ b/realtime_connext/poll_publisher.cxx @@ -1,13 +1,4 @@ -/******************************************************************************* - (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved. - RTI grants Licensee a license to use, modify, compile, and create derivative - works of the Software. Licensee has the right to distribute object form only - for use with RTI products. The Software is provided "as is", with no warranty - of any type, including any warranty for fitness for any purpose. RTI is under - no obligation to maintain or support the Software. RTI shall not be liable for - any incidental or consequential damages arising out of the use or inability to - use the software. - ******************************************************************************/ + /* poll_publisher.cxx A publication of data of type poll @@ -15,12 +6,12 @@ This file is derived from code automatically generated by the rtiddsgen command: - rtiddsgen -language C++ -example poll.idl +rtiddsgen -language C++ -example poll.idl Example publication of type poll automatically generated by 'rtiddsgen'. To test them follow these steps: - (1) Compile this file and the example subscription. +(1) Compile this file and the example subscription. (2) Start the subscription with the command objs//poll_subscriber @@ -37,17 +28,17 @@ Example: - - To run the example application on domain : - - On Unix: - - objs//poll_publisher o + +To run the example application on domain : + +On Unix: + +objs//poll_publisher o objs//poll_subscriber On Windows: - - objs\\poll_publisher + +objs\\poll_publisher objs\\poll_subscriber @@ -64,35 +55,207 @@ modification history #include "pollSupport.h" #include "ndds/ndds_cpp.h" -#include +/* Delete all entities */ +static int publisher_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ + /* + + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + status = -1; + } + */ + + return status; +} + +extern "C" int publisher_main(int domainId, int sample_count) +{ + DDSDomainParticipant *participant = NULL; + DDSPublisher *publisher = NULL; + DDSTopic *topic = NULL; + DDSDataWriter *writer = NULL; + pollDataWriter * poll_writer = NULL; + poll *instance = NULL; + DDS_ReturnCode_t retcode; + DDS_InstanceHandle_t instance_handle = DDS_HANDLE_NIL; + const char *type_name = NULL; + int count = 0; + DDS_Duration_t send_period = {4,0}; + + /* To customize participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize publisher QoS, use + the configuration file USER_QOS_PROFILES.xml */ + publisher = participant->create_publisher( + DDS_PUBLISHER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (publisher == NULL) { + printf("create_publisher error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Register type before creating topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + publisher_shutdown(participant); + return -1; + } + + /* To customize topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + publisher_shutdown(participant); + return -1; + } -#include "poll_utils.cxx" + /* To customize data writer QoS, use + the configuration file USER_QOS_PROFILES.xml */ + writer = publisher->create_datawriter( + topic, DDS_DATAWRITER_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (writer == NULL) { + printf("create_datawriter error\n"); + publisher_shutdown(participant); + return -1; + } + poll_writer = pollDataWriter::narrow(writer); + if (poll_writer == NULL) { + printf("DataWriter narrow error\n"); + publisher_shutdown(participant); + return -1; + } + /* Create data sample for writing */ + instance = pollTypeSupport::create_data(); + if (instance == NULL) { + printf("pollTypeSupport::create_data error\n"); + publisher_shutdown(participant); + return -1; + } + + /* For a data type that has a key, if the same instance is going to be + written multiple times, initialize the key here + and register the keyed instance prior to writing */ + /* + instance_handle = poll_writer->register_instance(*instance); + */ + + /* Main loop */ + for (count=0; (sample_count == 0) || (count < sample_count); ++count) { + + printf("Writing poll, count %d\n", count); + + /* Modify the data to be sent here */ + + retcode = poll_writer->write(*instance, instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("write error %d\n", retcode); + } + + NDDSUtility::sleep(send_period); + } + + /* + retcode = poll_writer->unregister_instance( + *instance, instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("unregister instance error %d\n", retcode); + } + */ + + /* Delete data sample */ + retcode = pollTypeSupport::delete_data(instance); + if (retcode != DDS_RETCODE_OK) { + printf("pollTypeSupport::delete_data error %d\n", retcode); + } + + /* Delete all entities */ + return publisher_shutdown(participant); +} #if defined(RTI_WINCE) int wmain(int argc, wchar_t** argv) { + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = _wtoi(argv[1]); + } + if (argc >= 3) { + sample_count = _wtoi(argv[2]); + } - /* Uncomment this to turn on additional logging - NDDSConfigLogger::get_instance()-> - set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, - NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); */ - + return publisher_main(domainId, sample_count); } - + #elif !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) int main(int argc, char *argv[]) { + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = atoi(argv[1]); + } + if (argc >= 3) { + sample_count = atoi(argv[2]); + } /* Uncomment this to turn on additional logging - NDDSConfigLogger::get_instance()-> - set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, - NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); */ - - return publisher_main(argc, argv); + + return publisher_main(domainId, sample_count); } #endif @@ -101,13 +264,13 @@ const unsigned char* __ctype = *(__ctypePtrGet()); extern "C" void usrAppInit () { -#ifdef USER_APPL_INIT - USER_APPL_INIT; /* for backwards compatibility */ -#endif - - /* add application specific code here */ + #ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ + #endif + + /* add application specific code here */ taskSpawn("pub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)publisher_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - + } #endif diff --git a/realtime_connext/poll_subscriber.cxx b/realtime_connext/poll_subscriber.cxx index 684dee3..aae517d 100644 --- a/realtime_connext/poll_subscriber.cxx +++ b/realtime_connext/poll_subscriber.cxx @@ -1,13 +1,4 @@ -/******************************************************************************* - (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved. - RTI grants Licensee a license to use, modify, compile, and create derivative - works of the Software. Licensee has the right to distribute object form only - for use with RTI products. The Software is provided "as is", with no warranty - of any type, including any warranty for fitness for any purpose. RTI is under - no obligation to maintain or support the Software. RTI shall not be liable for - any incidental or consequential damages arising out of the use or inability to - use the software. - ******************************************************************************/ + /* poll_subscriber.cxx A subscription example @@ -15,12 +6,12 @@ This file is derived from code automatically generated by the rtiddsgen command: - rtiddsgen -language C++ -example poll.idl +rtiddsgen -language C++ -example poll.idl Example subscription of type poll automatically generated by 'rtiddsgen'. To test them follow these steps: - (1) Compile this file and the example publication. +(1) Compile this file and the example publication. (2) Start the subscription with the command objs//poll_subscriber @@ -37,17 +28,17 @@ Example: - - To run the example application on domain : - - On Unix: - - objs//poll_publisher + +To run the example application on domain : + +On Unix: + +objs//poll_publisher objs//poll_subscriber On Windows: - - objs\\poll_publisher + +objs\\poll_publisher objs\\poll_subscriber @@ -64,17 +55,212 @@ modification history #include "pollSupport.h" #include "ndds/ndds_cpp.h" -#include "poll_utils.cxx" +class pollListener : public DDSDataReaderListener { + public: + virtual void on_requested_deadline_missed( + DDSDataReader* /*reader*/, + const DDS_RequestedDeadlineMissedStatus& /*status*/) {} + + virtual void on_requested_incompatible_qos( + DDSDataReader* /*reader*/, + const DDS_RequestedIncompatibleQosStatus& /*status*/) {} + + virtual void on_sample_rejected( + DDSDataReader* /*reader*/, + const DDS_SampleRejectedStatus& /*status*/) {} + + virtual void on_liveliness_changed( + DDSDataReader* /*reader*/, + const DDS_LivelinessChangedStatus& /*status*/) {} + + virtual void on_sample_lost( + DDSDataReader* /*reader*/, + const DDS_SampleLostStatus& /*status*/) {} + + virtual void on_subscription_matched( + DDSDataReader* /*reader*/, + const DDS_SubscriptionMatchedStatus& /*status*/) {} + + virtual void on_data_available(DDSDataReader* reader); +}; + +void pollListener::on_data_available(DDSDataReader* reader) +{ + pollDataReader *poll_reader = NULL; + pollSeq data_seq; + DDS_SampleInfoSeq info_seq; + DDS_ReturnCode_t retcode; + int i; + + poll_reader = pollDataReader::narrow(reader); + if (poll_reader == NULL) { + printf("DataReader narrow error\n"); + return; + } + + retcode = poll_reader->take( + data_seq, info_seq, DDS_LENGTH_UNLIMITED, + DDS_ANY_SAMPLE_STATE, DDS_ANY_VIEW_STATE, DDS_ANY_INSTANCE_STATE); + + if (retcode == DDS_RETCODE_NO_DATA) { + return; + } else if (retcode != DDS_RETCODE_OK) { + printf("take error %d\n", retcode); + return; + } + + for (i = 0; i < data_seq.length(); ++i) { + if (info_seq[i].valid_data) { + pollTypeSupport::print_data(&data_seq[i]); + } + } + + retcode = poll_reader->return_loan(data_seq, info_seq); + if (retcode != DDS_RETCODE_OK) { + printf("return loan error %d\n", retcode); + } +} + +/* Delete all entities */ +static int subscriber_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides the finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ + /* + + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + status = -1; + } + */ + return status; +} + +extern "C" int subscriber_main(int domainId, int sample_count) +{ + DDSDomainParticipant *participant = NULL; + DDSSubscriber *subscriber = NULL; + DDSTopic *topic = NULL; + pollListener *reader_listener = NULL; + DDSDataReader *reader = NULL; + DDS_ReturnCode_t retcode; + const char *type_name = NULL; + int count = 0; + DDS_Duration_t receive_period = {4,0}; + int status = 0; + + /* To customize the participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the subscriber QoS, use + the configuration file USER_QOS_PROFILES.xml */ + subscriber = participant->create_subscriber( + DDS_SUBSCRIBER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (subscriber == NULL) { + printf("create_subscriber error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Register the type before creating the topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Create a data reader listener */ + reader_listener = new pollListener(); + + /* To customize the data reader QoS, use + the configuration file USER_QOS_PROFILES.xml */ + reader = subscriber->create_datareader( + topic, DDS_DATAREADER_QOS_DEFAULT, reader_listener, + DDS_STATUS_MASK_ALL); + if (reader == NULL) { + printf("create_datareader error\n"); + subscriber_shutdown(participant); + delete reader_listener; + return -1; + } + + /* Main loop */ + for (count=0; (sample_count == 0) || (count < sample_count); ++count) { + + printf("poll subscriber sleeping for %d sec...\n", + receive_period.sec); + + NDDSUtility::sleep(receive_period); + } + + /* Delete all entities */ + status = subscriber_shutdown(participant); + delete reader_listener; + + return status; +} #if defined(RTI_WINCE) int wmain(int argc, wchar_t** argv) { - - + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = _wtoi(argv[1]); + } + if (argc >= 3) { + sample_count = _wtoi(argv[2]); + } + /* Uncomment this to turn on additional logging - NDDSConfigLogger::get_instance()-> - set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, - NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); */ return subscriber_main(domainId, sample_count); @@ -83,15 +269,23 @@ int wmain(int argc, wchar_t** argv) #elif !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) int main(int argc, char *argv[]) { + int domainId = 0; + int sample_count = 0; /* infinite loop */ + if (argc >= 2) { + domainId = atoi(argv[1]); + } + if (argc >= 3) { + sample_count = atoi(argv[2]); + } /* Uncomment this to turn on additional logging - NDDSConfigLogger::get_instance()-> - set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, - NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); */ - - return subscriber_main(argc, argv); + + return subscriber_main(domainId, sample_count); } #endif @@ -100,13 +294,12 @@ const unsigned char* __ctype = *(__ctypePtrGet()); extern "C" void usrAppInit () { -#ifdef USER_APPL_INIT - USER_APPL_INIT; /* for backwards compatibility */ -#endif - - /* add application specific code here */ + #ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ + #endif + + /* add application specific code here */ taskSpawn("sub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)subscriber_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - + } #endif - diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index cdb72f6..55e72d1 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -14,6 +14,8 @@ #include +unsigned int samples_received = 0; + struct PublisherNode { pollDataWriter * poll_writer; @@ -33,6 +35,7 @@ struct Arguments static int subscriber_shutdown( DDSDomainParticipant *participant) { + printf("Samples received by subscriber: %d\n", samples_received); DDS_ReturnCode_t retcode; int status = 0; @@ -94,6 +97,7 @@ void *subscriber_callback(void *args) continue; len ++; sum += data_seq[i].seq; + ++samples_received; } /* From ff8b9dd7a96a1b17771f62d4cc106cbf70ec44f8 Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 8 Jul 2015 17:17:21 -0700 Subject: [PATCH 28/34] Fixed opensplice examples --- realtime/ExamplePublisher.hpp | 10 +++++++++- realtime/check_status.h | 2 +- realtime/dds_intraproc.cpp | 14 ++++++++++---- realtime/dds_lmp.cpp | 2 +- realtime/dds_lms.cpp | 5 ++++- realtime/idl/LargeMsg.idl | 3 ++- realtime_c/rt_intraproc.cpp | 12 +++++++++--- realtime_c/rt_publisher.cpp | 7 +++++-- realtime_c/rt_subscriber.cpp | 6 +++++- realtime_connext/poll_utils.cxx | 8 ++++++-- 10 files changed, 52 insertions(+), 17 deletions(-) diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp index b4867fe..8697a21 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/ExamplePublisher.hpp @@ -103,6 +103,15 @@ bool ExamplePublisher::init() this->msg.content = std::string(this->message_size, '.').c_str(); checkHandle(&msg, "new LargeMsg::LargeMessage"); + this->instance_handle = this->data_writer->register_instance(msg); + status = data_writer->write(msg, instance_handle); + /* + if (this->instance_handle == DDS::HANDLE_NIL) + { + std::cout << "Instance handle was NIL" << std::endl; + exit(-1); + } + */ std::cout << "Ready to send LargeMessage's" << std::endl; return true; @@ -112,7 +121,6 @@ void ExamplePublisher::callback() { this->msg.seq = this->i; ++i; - this->instance_handle = this->data_writer->register_instance(msg); status = data_writer->write(msg, instance_handle); diff --git a/realtime/check_status.h b/realtime/check_status.h index eefab3d..2f5b804 100644 --- a/realtime/check_status.h +++ b/realtime/check_status.h @@ -30,7 +30,7 @@ void checkStatus(DDS::ReturnCode_t status, const char *info) if (status != DDS::RETCODE_OK && status != DDS::RETCODE_NO_DATA) { std::cerr << "Error in " << info << ": " << getErrorName(status) << std::endl; - //exit (1); + exit (1); } } diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index 9f77928..bfad684 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -59,10 +59,13 @@ void *publisher_thread(void *unused) void *subscriber_thread(void *unused) { rttest_init_new_thread(); - rttest_set_sched_priority(98, SCHED_RR); + if (rttest_set_sched_priority(98, SCHED_RR) != 0) + { + perror("Failed to set scheduling priorty and policy of thread"); + } rttest_spin(sub_callback, NULL); - + rttest_write_results_file("rttest_subscriber_results"); std::cout << "Subscriber received " << sub->msgs_count << " messages." << std::endl; /*if (sub != NULL) @@ -109,13 +112,16 @@ int main(int argc, char *argv[]) if (rttest_lock_and_prefault_dynamic(pool_size) != 0) { - perror("Failed to lock dynamic memory. Process might not be real-time safe"); + perror("Failed to lock dynamic memory"); } rttest_prefault_stack_size(stack_size); start_rt_thread(&subscriber_thread); - rttest_set_sched_priority(98, SCHED_RR); + if (rttest_set_sched_priority(98, SCHED_RR) != 0) + { + perror("Failed to set scheduling priority and policy"); + } publisher_thread(NULL); /* diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index f57a75f..e55809e 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) } - if (rttest_lock_and_prefault_dynamic(pool_size) != 0) + if (rttest_lock_memory() != 0) { perror("Failed to lock dynamic memory"); } diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index 0a00ef4..be3a332 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -17,7 +17,10 @@ int main(int argc, char *argv[]) sub->init(); rttest_read_args(argc, argv); - rttest_set_sched_priority(90, SCHED_RR); + if (rttest_set_sched_priority(90, SCHED_RR) != 0) + { + perror("Failed to set scheduling priority and policy of thread"); + } size_t pool_size = 1024*1024*1024; size_t stack_size = sizeof(*sub) + 1024*1024; diff --git a/realtime/idl/LargeMsg.idl b/realtime/idl/LargeMsg.idl index 89ece6e..e22ded6 100644 --- a/realtime/idl/LargeMsg.idl +++ b/realtime/idl/LargeMsg.idl @@ -1,7 +1,8 @@ module LargeMsg { struct LargeMessage { + long key; long seq; // Message sequence number string content; // message body }; -#pragma keylist LargeMessage seq +#pragma keylist LargeMessage key }; diff --git a/realtime_c/rt_intraproc.cpp b/realtime_c/rt_intraproc.cpp index 0a1b864..e8fc0cd 100644 --- a/realtime_c/rt_intraproc.cpp +++ b/realtime_c/rt_intraproc.cpp @@ -56,7 +56,11 @@ void *publisher_thread(void *unused) void *subscriber_thread(void *unused) { rttest_init_new_thread(); - rttest_set_sched_priority(98, SCHED_RR); + if (rttest_set_sched_priority(97, SCHED_RR) != 0) + { + perror("Failed to set scheduling priority and policy of thread"); + } + rttest_spin(sub_callback, NULL); @@ -111,7 +115,9 @@ int main(int argc, char *argv[]) start_rt_thread(&subscriber_thread); - rttest_set_sched_priority(98, SCHED_RR); - + if (rttest_set_sched_priority(98, SCHED_RR) != 0) + { + perror("Failed to set scheduling priority and policy of thread"); + } publisher_thread(NULL); } diff --git a/realtime_c/rt_publisher.cpp b/realtime_c/rt_publisher.cpp index 355a8d4..d75eeb2 100644 --- a/realtime_c/rt_publisher.cpp +++ b/realtime_c/rt_publisher.cpp @@ -45,8 +45,11 @@ int main(int argc, char *argv[]) pub.init(); rttest_read_args(argc, argv); - rttest_set_sched_priority(90, SCHED_RR); - getchar(); + if (rttest_set_sched_priority(90, SCHED_RR) != 0) + { + perror("Failed to set scheduling priority and policy of thread"); + } + if (rttest_lock_memory() != 0) { perror("Failed to lock memory"); diff --git a/realtime_c/rt_subscriber.cpp b/realtime_c/rt_subscriber.cpp index cd8b6e0..bd53654 100644 --- a/realtime_c/rt_subscriber.cpp +++ b/realtime_c/rt_subscriber.cpp @@ -15,7 +15,11 @@ int main(int argc, char *argv[]) sub.init(); rttest_read_args(argc, argv); - rttest_set_sched_priority(90, SCHED_RR); + + if (rttest_set_sched_priority(90, SCHED_RR) != 0) + { + perror("Failed to set scheduling priority and policy of thread"); + } if (rttest_lock_memory() != 0) { diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index 55e72d1..ab2b9ac 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -211,7 +211,9 @@ int subscriber_main(int argc, char *argv[]) return -1; } - rttest_set_sched_priority(SCHED_RR, 97); + if (rttest_set_sched_priority(97, SCHED_RR) != 0) { + perror("Failed to set scheduling priority"); + } if (rttest_lock_memory() != 0) { perror("Couldn't lock memory"); @@ -422,7 +424,9 @@ int publisher_main(int argc, char *argv[]) /* Initialize random seed before entering the loop */ // srand(time(NULL)); - rttest_set_sched_priority(SCHED_RR, 98); + if (rttest_set_sched_priority(98, SCHED_RR) != 0) { + perror("Failed to set scheduling priority"); + } if (rttest_lock_memory() != 0) { perror("Couldn't lock memory"); From fafe2b21b008b97aa202532da41e1cb207bc2aa0 Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 8 Jul 2015 17:37:39 -0700 Subject: [PATCH 29/34] Tweak all the examples to show changing memory doesn't affect performance --- realtime/ExamplePublisher.hpp | 4 ++++ realtime_c/ExamplePublisher.hpp | 6 +++--- realtime_c/LargeMsg.idl | 3 ++- realtime_connext/poll_utils.cxx | 6 +++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/realtime/ExamplePublisher.hpp b/realtime/ExamplePublisher.hpp index 8697a21..6abbbf2 100644 --- a/realtime/ExamplePublisher.hpp +++ b/realtime/ExamplePublisher.hpp @@ -121,6 +121,10 @@ void ExamplePublisher::callback() { this->msg.seq = this->i; ++i; + for (int j = 0; j < this->message_size; ++j) + { + this->msg.content[j] = i; + } status = data_writer->write(msg, instance_handle); diff --git a/realtime_c/ExamplePublisher.hpp b/realtime_c/ExamplePublisher.hpp index 9897961..0a0cf2b 100644 --- a/realtime_c/ExamplePublisher.hpp +++ b/realtime_c/ExamplePublisher.hpp @@ -18,6 +18,7 @@ class ExamplePublisher LargeMsg_LargeMessageDataWriter talker; LargeMsg_LargeMessage msg; DDS_ReturnCode_t status; + DDS_InstanceHandle_t userHandle; int i; @@ -181,6 +182,7 @@ bool ExamplePublisher::init() // register a chat message + userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, &msg); printf("Created user handle and preallocated message.\n"); return true; } @@ -192,12 +194,10 @@ void ExamplePublisher::callback() int j; for (j < 0; j < this->message_size; ++j) { - msg.content[j] = '.'; + msg.content[j] = i; } - DDS_InstanceHandle_t userHandle = LargeMsg_LargeMessageDataWriter_register_instance(talker, &msg); status = LargeMsg_LargeMessageDataWriter_write(talker, &msg, userHandle); - //LargeMsg_LargeMessageDataWriter_unregister_instance(talker, msg, userHandle ); checkStatus(status, "LargeMsg_LargeMessageDataWriter_write"); ++i; } diff --git a/realtime_c/LargeMsg.idl b/realtime_c/LargeMsg.idl index 89ece6e..e22ded6 100644 --- a/realtime_c/LargeMsg.idl +++ b/realtime_c/LargeMsg.idl @@ -1,7 +1,8 @@ module LargeMsg { struct LargeMessage { + long key; long seq; // Message sequence number string content; // message body }; -#pragma keylist LargeMessage seq +#pragma keylist LargeMessage key }; diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index ab2b9ac..f213636 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -22,7 +22,7 @@ struct PublisherNode poll *instance; DDS_InstanceHandle_t instance_handle; int count; - //std::string content; + unsigned int message_length; }; struct Arguments @@ -287,6 +287,9 @@ void *publisher_callback(void *args) /* TODO Modify the data to be written here */ /* Set x to a random number between 0 and 9 */ pub_node->instance->seq = (int)(rand()/(RAND_MAX/10.0)); + for (int j = 0; j < pub_node->message_length; j++) { + pub_node->instance->content[j] = pub_node->count; + } DDS_ReturnCode_t retcode = pub_node->poll_writer->write(*pub_node->instance, pub_node->instance_handle); if (retcode != DDS_RETCODE_OK) { @@ -420,6 +423,7 @@ int publisher_main(int argc, char *argv[]) pub_node.instance_handle = instance_handle; pub_node.poll_writer = poll_writer; pub_node.count = 0; + pub_node.message_length = message_length; /* Initialize random seed before entering the loop */ // srand(time(NULL)); From f9e7731a22a6c9624f706fa0719fa101aecc4979 Mon Sep 17 00:00:00 2001 From: Jackie Date: Wed, 8 Jul 2015 18:44:50 -0700 Subject: [PATCH 30/34] prefault cleanup, 7 is the magic number --- realtime/CMakeLists.txt | 6 ------ realtime/dds_intraproc.cpp | 6 ++---- realtime/dds_lmp.cpp | 6 +----- realtime/dds_lms.cpp | 7 ++----- realtime_c/CMakeLists.txt | 9 +++------ realtime_c/rt_intraproc.cpp | 4 +--- realtime_c/rt_publisher.cpp | 3 +-- realtime_c/rt_subscriber.cpp | 2 +- realtime_connext/CMakeLists.txt | 2 +- realtime_connext/poll_utils.cxx | 3 +++ 10 files changed, 15 insertions(+), 33 deletions(-) diff --git a/realtime/CMakeLists.txt b/realtime/CMakeLists.txt index 8657106..8a6b33e 100644 --- a/realtime/CMakeLists.txt +++ b/realtime/CMakeLists.txt @@ -4,12 +4,9 @@ set (CMAKE_CXX_FLAGS "-std=c++11") find_package(rttest REQUIRED) -#include(ExamplePublisher.hpp ExampleSubscriber.hpp) - link_directories(${rttest_LIBRARY_DIR}) include_directories(${rttest_INCLUDE_DIRS}) - find_package(opensplice REQUIRED) include_directories(${OPENSPLICE_INCLUDE_DIRS}) @@ -21,9 +18,6 @@ target_link_libraries(dds_lms ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) add_executable(dds_lmp dds_lmp.cpp) target_link_libraries(dds_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) -#add_executable(dds_unsafe_lmp dds_unsafe_lmp.cpp) -#target_link_libraries(dds_unsafe_lmp ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) - find_package(Threads) if(NOT Threads_FOUND) message(WARNING "pthread not found. Real-time intra-process pub/sub example will not be built.") diff --git a/realtime/dds_intraproc.cpp b/realtime/dds_intraproc.cpp index bfad684..cc2b41d 100644 --- a/realtime/dds_intraproc.cpp +++ b/realtime/dds_intraproc.cpp @@ -107,14 +107,12 @@ int main(int argc, char *argv[]) pub->init(); sub = new ExampleSubscriber(); sub->init(); - size_t stack_size = message_length*2 + sizeof(*pub) + sizeof(*sub); - size_t pool_size = 2*message_length; - if (rttest_lock_and_prefault_dynamic(pool_size) != 0) + if (rttest_lock_memory() != 0) { perror("Failed to lock dynamic memory"); } - rttest_prefault_stack_size(stack_size); + rttest_prefault_stack(); start_rt_thread(&subscriber_thread); diff --git a/realtime/dds_lmp.cpp b/realtime/dds_lmp.cpp index e55809e..982332d 100644 --- a/realtime/dds_lmp.cpp +++ b/realtime/dds_lmp.cpp @@ -42,8 +42,6 @@ int main(int argc, char *argv[]) } rttest_read_args(argc, argv); - //getchar(); - pub = new ExamplePublisher; pub->message_size = message_length; @@ -60,9 +58,7 @@ int main(int argc, char *argv[]) perror("Failed to lock dynamic memory"); } - //rttest_prefault_stack_size(stack_size); - - //clock_nanosleep(0, 0, &t, 0); + rttest_prefault_stack(); rttest_spin(pub_callback, NULL); diff --git a/realtime/dds_lms.cpp b/realtime/dds_lms.cpp index be3a332..a0934d5 100644 --- a/realtime/dds_lms.cpp +++ b/realtime/dds_lms.cpp @@ -24,15 +24,12 @@ int main(int argc, char *argv[]) size_t pool_size = 1024*1024*1024; size_t stack_size = sizeof(*sub) + 1024*1024; - /* - getchar(); - if (rttest_lock_and_prefault_dynamic(pool_size) != 0) + if (rttest_lock_memory() != 0) { perror("Failed to lock memory"); } - */ - rttest_prefault_stack_size(stack_size); + rttest_prefault_stack(); rttest_spin(sub_callback, NULL); diff --git a/realtime_c/CMakeLists.txt b/realtime_c/CMakeLists.txt index 51234eb..d106a4b 100644 --- a/realtime_c/CMakeLists.txt +++ b/realtime_c/CMakeLists.txt @@ -15,17 +15,14 @@ link_directories(${OPENSPLICE_LIBRARY_DIRS} ${rttest_LIBRARY_DIR}) set(MSG_C_FILES c/LargeMsgSacDcps.c c/LargeMsgSplDcps.c) add_executable(publisher rt_publisher.cpp ${MSG_C_FILES}) -target_link_libraries(publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) +target_link_libraries(publisher ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) add_executable(subscriber rt_subscriber.cpp ${MSG_C_FILES}) -target_link_libraries(subscriber ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) +target_link_libraries(subscriber ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES}) if(NOT Threads_FOUND) message(WARNING "pthread not found. Real-time intra-process pub/sub example will not be built.") elseif(Threads_FOUND) add_executable(intraproc rt_intraproc.cpp ${MSG_C_FILES}) - target_link_libraries(intraproc ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} m stdc++) + target_link_libraries(intraproc ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) endif() - -#add_executable(intraproc rt_intraproc.cpp ${MSG_C_FILES}) -#target_link_libraries(intraproc ${OPENSPLICE_LIBRARIES} ${rttest_LIBRARIES} m stdc++) diff --git a/realtime_c/rt_intraproc.cpp b/realtime_c/rt_intraproc.cpp index e8fc0cd..11b1896 100644 --- a/realtime_c/rt_intraproc.cpp +++ b/realtime_c/rt_intraproc.cpp @@ -104,14 +104,12 @@ int main(int argc, char *argv[]) pub->init(); sub = new ExampleSubscriber(); sub->init(); - //size_t stack_size = message_length*2 + sizeof(*pub) + sizeof(*sub); - //size_t pool_size = 2*message_length; if (rttest_lock_memory() != 0) { perror("Failed to lock dynamic memory. Process might not be real-time safe"); } - //rttest_prefault_stack_size(stack_size); + rttest_prefault_stack(); start_rt_thread(&subscriber_thread); diff --git a/realtime_c/rt_publisher.cpp b/realtime_c/rt_publisher.cpp index d75eeb2..80fbb0b 100644 --- a/realtime_c/rt_publisher.cpp +++ b/realtime_c/rt_publisher.cpp @@ -54,8 +54,7 @@ int main(int argc, char *argv[]) { perror("Failed to lock memory"); } - //rttest_prefault_stack_size(STACK_SIZE); - //rttest_lock_and_prefault_dynamic(STACK_SIZE); + rttest_prefault_stack(); rttest_spin(pub_callback, NULL); diff --git a/realtime_c/rt_subscriber.cpp b/realtime_c/rt_subscriber.cpp index bd53654..1894bf5 100644 --- a/realtime_c/rt_subscriber.cpp +++ b/realtime_c/rt_subscriber.cpp @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) perror("Failed to lock memory"); } - //rttest_prefault_stack_size(STACK_SIZE); + rttest_prefault_stack(); rttest_spin(sub_callback, NULL); diff --git a/realtime_connext/CMakeLists.txt b/realtime_connext/CMakeLists.txt index 57a8d28..00044a3 100644 --- a/realtime_connext/CMakeLists.txt +++ b/realtime_connext/CMakeLists.txt @@ -11,7 +11,7 @@ add_definitions(${nddscpp_DEFINITIONS}) link_directories(${rttest_LIBRARY_DIR}) include_directories(${rttest_INCLUDE_DIRS} ${nddscpp_INCLUDE_DIRS}) -set(CMAKE_CXX_FLAGS ${rttest_FLAGS}) +set(CMAKE_CXX_FLAGS "-std=c++11") add_library(poll_msg poll.cxx pollPlugin.cxx pollSupport.cxx) target_link_libraries(poll_msg ${nddscpp_LIBRARIES}) diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index f213636..8244715 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -218,6 +218,7 @@ int subscriber_main(int argc, char *argv[]) if (rttest_lock_memory() != 0) { perror("Couldn't lock memory"); } + rttest_prefault_stack(); /* Main loop */ // TODO rttest_spin here @@ -435,6 +436,8 @@ int publisher_main(int argc, char *argv[]) if (rttest_lock_memory() != 0) { perror("Couldn't lock memory"); } + rttest_prefault_stack(); + rttest_spin(publisher_callback, static_cast(&pub_node)); rttest_write_results_file("rttest_publisher_results"); rttest_finish(); From abaf9d5401ae20b2c1ff02adaec138e95ac34a6c Mon Sep 17 00:00:00 2001 From: Jackie Date: Thu, 9 Jul 2015 10:48:12 -0700 Subject: [PATCH 31/34] lazy memory cleanup in connext --- realtime_connext/poll.idl | 3 ++- realtime_connext/poll_utils.cxx | 15 +++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/realtime_connext/poll.idl b/realtime_connext/poll.idl index a5be389..7a8c9e0 100644 --- a/realtime_connext/poll.idl +++ b/realtime_connext/poll.idl @@ -9,7 +9,8 @@ use the software. ******************************************************************************/ struct poll { + long key; long seq; string content; }; - +#pragma keylist poll key diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index 8244715..fa52100 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -57,13 +57,11 @@ static int subscriber_shutdown( domain participant factory for people who want to release memory used by the participant factory. Uncomment the following block of code for clean destruction of the singleton. */ -/* retcode = DDSDomainParticipantFactory::finalize_instance(); if (retcode != DDS_RETCODE_OK) { printf("finalize_instance error %d\n", retcode); - status = -1; + //status = -1; } -*/ return status; } @@ -221,7 +219,6 @@ int subscriber_main(int argc, char *argv[]) rttest_prefault_stack(); /* Main loop */ - // TODO rttest_spin here rttest_spin(subscriber_callback, static_cast(poll_reader)); /* Delete all entities */ @@ -270,13 +267,11 @@ static int publisher_shutdown( domain participant factory for people who want to release memory used by the participant factory. Uncomment the following block of code for clean destruction of the singleton. */ -/* retcode = DDSDomainParticipantFactory::finalize_instance(); if (retcode != DDS_RETCODE_OK) { printf("finalize_instance error %d\n", retcode); - status = -1; + //status = -1; } -*/ return status; } @@ -285,7 +280,6 @@ void *publisher_callback(void *args) { PublisherNode *pub_node = static_cast(args); // message instance, instance_handle, poll_writer - /* TODO Modify the data to be written here */ /* Set x to a random number between 0 and 9 */ pub_node->instance->seq = (int)(rand()/(RAND_MAX/10.0)); for (int j = 0; j < pub_node->message_length; j++) { @@ -416,9 +410,8 @@ int publisher_main(int argc, char *argv[]) /* For a data type that has a key, if the same instance is going to be written multiple times, initialize the key here and register the keyed instance prior to writing */ -/* instance_handle = poll_writer->register_instance(*instance); -*/ + PublisherNode pub_node; pub_node.instance = instance; pub_node.instance_handle = instance_handle; @@ -442,13 +435,11 @@ int publisher_main(int argc, char *argv[]) rttest_write_results_file("rttest_publisher_results"); rttest_finish(); -/* retcode = poll_writer->unregister_instance( *instance, instance_handle); if (retcode != DDS_RETCODE_OK) { printf("unregister instance error %d\n", retcode); } -*/ /* Delete data sample */ retcode = pollTypeSupport::delete_data(instance); From 49f47e0ee2442d89ccb8da9dfb84d802e8fe178d Mon Sep 17 00:00:00 2001 From: Jackie Date: Thu, 9 Jul 2015 12:01:46 -0700 Subject: [PATCH 32/34] More mem management --- realtime_connext/poll_utils.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index fa52100..8209394 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -57,11 +57,13 @@ static int subscriber_shutdown( domain participant factory for people who want to release memory used by the participant factory. Uncomment the following block of code for clean destruction of the singleton. */ + /* retcode = DDSDomainParticipantFactory::finalize_instance(); if (retcode != DDS_RETCODE_OK) { printf("finalize_instance error %d\n", retcode); //status = -1; } + */ return status; } From 69a5cd6600260954e31c01189c7efbe0c6ded96a Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Thu, 9 Jul 2015 13:30:45 -0700 Subject: [PATCH 33/34] Pull in connext examples --- realtime_connext/CMakeLists.txt | 31 ++ realtime_connext/USER_QOS_PROFILES.xml | 114 ++++++ realtime_connext/build.sh | 8 + realtime_connext/makefile | 76 ++++ realtime_connext/poll.idl | 16 + realtime_connext/poll_intraproc.cxx | 42 +++ realtime_connext/poll_publisher.cxx | 276 +++++++++++++++ realtime_connext/poll_subscriber.cxx | 305 ++++++++++++++++ realtime_connext/poll_utils.cxx | 468 +++++++++++++++++++++++++ 9 files changed, 1336 insertions(+) create mode 100644 realtime_connext/CMakeLists.txt create mode 100644 realtime_connext/USER_QOS_PROFILES.xml create mode 100644 realtime_connext/build.sh create mode 100644 realtime_connext/makefile create mode 100644 realtime_connext/poll.idl create mode 100644 realtime_connext/poll_intraproc.cxx create mode 100644 realtime_connext/poll_publisher.cxx create mode 100644 realtime_connext/poll_subscriber.cxx create mode 100644 realtime_connext/poll_utils.cxx diff --git a/realtime_connext/CMakeLists.txt b/realtime_connext/CMakeLists.txt new file mode 100644 index 0000000..00044a3 --- /dev/null +++ b/realtime_connext/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +project(realtime_connext) + + +find_package(nddscpp REQUIRED) +find_package(rttest REQUIRED) + +add_definitions(${nddscpp_DEFINITIONS}) + +link_directories(${rttest_LIBRARY_DIR}) +include_directories(${rttest_INCLUDE_DIRS} ${nddscpp_INCLUDE_DIRS}) + +set(CMAKE_CXX_FLAGS "-std=c++11") + +add_library(poll_msg poll.cxx pollPlugin.cxx pollSupport.cxx) +target_link_libraries(poll_msg ${nddscpp_LIBRARIES}) + +add_executable(poll_publisher poll_publisher.cxx) +target_link_libraries(poll_publisher poll_msg ${rttest_LIBRARIES}) + +add_executable(poll_subscriber poll_subscriber.cxx) +target_link_libraries(poll_subscriber poll_msg ${rttest_LIBRARIES}) + +find_package(Threads) +if(NOT Threads_FOUND) + message(WARNING "pthread not found. Intra-process pub/sub example will not be built") +elseif (Threads_FOUND) + add_executable(poll_intraproc poll_intraproc.cxx) + target_link_libraries(poll_intraproc poll_msg ${rttest_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +endif() diff --git a/realtime_connext/USER_QOS_PROFILES.xml b/realtime_connext/USER_QOS_PROFILES.xml new file mode 100644 index 0000000..374b827 --- /dev/null +++ b/realtime_connext/USER_QOS_PROFILES.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + pollDataWriter + + + + + + + pollDataReader + + + + + + + pollParticipant + pollParticipantRole + + + + + + + diff --git a/realtime_connext/build.sh b/realtime_connext/build.sh new file mode 100644 index 0000000..484d63d --- /dev/null +++ b/realtime_connext/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rtiddsgen2 poll.idl -replace -language C++ -example x64Linux3.xgcc4.6.3 + +mkdir build +cd build +cmake .. +make diff --git a/realtime_connext/makefile b/realtime_connext/makefile new file mode 100644 index 0000000..46a812e --- /dev/null +++ b/realtime_connext/makefile @@ -0,0 +1,76 @@ +###################################################################### +# makefile_async_x64Linux3.xgcc4.6.3 +# +# (c) Copyright, Real-Time Innovations, 2012. All rights reserved. +# No duplications, whole or partial, manual or electronic, may be made +# without express written permission. Any such copies, or +# revisions thereof, must display this notice unaltered. +# This code contains trade secrets of Real-Time Innovations, Inc. +# +# +# This makefile was automatically generated by rtiddsgen. +# +# To compile, type: +# gmake -f makefile_async_x64Linux3.xgcc4.6.3 +# +# Note: This makefile is only meant to build our example applications and +# may require alterations to build on your system. +# +# This makefile assumes that your build environment is already correctly +# configured. (For example, the correct version of your compiler and +# linker should be on your PATH.) +###################################################################### + +c_cc_x64Linux3.xgcc4.6.3 = gcc +c_cc_flags_x64Linux3.xgcc4.6.3 = -m64 -Wall +c_ld_x64Linux3.xgcc4.6.3 = gcc +c_ld_flags_x64Linux3.xgcc4.6.3 = -m64 +cxx_cc_x64Linux3.xgcc4.6.3 = g++ +cxx_cc_flags_x64Linux3.xgcc4.6.3 = -m64 -Wall +cxx_ld_x64Linux3.xgcc4.6.3 = g++ +cxx_ld_flags_x64Linux3.xgcc4.6.3 = -m64 -static-libgcc +syslibs_x64Linux3.xgcc4.6.3 = -ldl -lnsl -lm -lpthread -lrt +DEFINES_ARCH_SPECIFIC = -DRTI_UNIX -DRTI_LINUX -DRTI_64BIT + + +DEFINES = $(DEFINES_ARCH_SPECIFIC) $(cxx_DEFINES_ARCH_SPECIFIC) + +INCLUDES = -I. -I$(NDDSHOME)/include -I$(NDDSHOME)/include/ndds + +LIBS = -L$(NDDSHOME)/lib/x64Linux3.xgcc4.6.3 \ + -lnddscppz -lnddscz -lnddscorez $(syslibs_x64Linux3.xgcc4.6.3) + +CDRSOURCES = async.idl +COMMONSOURCES = asyncPlugin.cxx asyncSupport.cxx async.cxx +EXEC = async_publisher async_subscriber +DIRECTORIES = objs.dir objs/x64Linux3.xgcc4.6.3.dir +COMMONOBJS = $(COMMONSOURCES:%.cxx=objs/x64Linux3.xgcc4.6.3/%.o) + +# We actually stick the objects in a sub directory to keep your directory clean. +x64Linux3.xgcc4.6.3 : $(DIRECTORIES) $(COMMONOBJS) \ + $(EXEC:%=objs/x64Linux3.xgcc4.6.3/%.o) \ + $(EXEC:%=objs/x64Linux3.xgcc4.6.3/%.out) + +objs/x64Linux3.xgcc4.6.3/%.out : objs/x64Linux3.xgcc4.6.3/%.o + $(cxx_ld_x64Linux3.xgcc4.6.3) $(cxx_ld_flags_x64Linux3.xgcc4.6.3) -o $(@:%.out=%) $(@:%.out=%.o) $(COMMONOBJS) $(LIBS) + +objs/x64Linux3.xgcc4.6.3/%.o : %.cxx + $(cxx_cc_x64Linux3.xgcc4.6.3) $(cxx_cc_flags_x64Linux3.xgcc4.6.3) -o $@ $(DEFINES) $(INCLUDES) -c $< + +# +# Uncomment these lines if you want the support files regenerated when idl +# file is modified +# +async.cxx async.h \ +asyncPlugin.cxx asyncPlugin.h \ +asyncSupport.cxx asyncSupport.h : \ + async.idl + rtiddsgen2 async.idl -replace + +# Here is how we create those subdirectories automatically. +%.dir : + @echo "Checking directory $*" + @if [ ! -d $* ]; then \ + echo "Making directory $*"; \ + mkdir -p $* ; \ + fi; diff --git a/realtime_connext/poll.idl b/realtime_connext/poll.idl new file mode 100644 index 0000000..7a8c9e0 --- /dev/null +++ b/realtime_connext/poll.idl @@ -0,0 +1,16 @@ +/******************************************************************************* + (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved. + RTI grants Licensee a license to use, modify, compile, and create derivative + works of the Software. Licensee has the right to distribute object form only + for use with RTI products. The Software is provided "as is", with no warranty + of any type, including any warranty for fitness for any purpose. RTI is under + no obligation to maintain or support the Software. RTI shall not be liable for + any incidental or consequential damages arising out of the use or inability to + use the software. + ******************************************************************************/ +struct poll { + long key; + long seq; + string content; +}; +#pragma keylist poll key diff --git a/realtime_connext/poll_intraproc.cxx b/realtime_connext/poll_intraproc.cxx new file mode 100644 index 0000000..24ff8f8 --- /dev/null +++ b/realtime_connext/poll_intraproc.cxx @@ -0,0 +1,42 @@ +#include "poll_utils.cxx" + +#if !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) +int main(int argc, char *argv[]) +{ + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + Arguments args; + args.argc = argc; + args.argv = argv; + + pthread_t thread; + pthread_attr_t attr; + if (pthread_attr_init(&attr)) + { + fprintf(stderr, "Couldn't initialize pthread to default value"); + exit(1); + } + pthread_create(&thread, &attr, publisher_main, static_cast(&args)); + return subscriber_main(&args); +} +#endif + +#ifdef RTI_VX653 +const unsigned char* __ctype = *(__ctypePtrGet()); + +extern "C" void usrAppInit () +{ +#ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ +#endif + + /* add application specific code here */ + taskSpawn("pub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)publisher_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +} +#endif + diff --git a/realtime_connext/poll_publisher.cxx b/realtime_connext/poll_publisher.cxx new file mode 100644 index 0000000..3e26727 --- /dev/null +++ b/realtime_connext/poll_publisher.cxx @@ -0,0 +1,276 @@ + +/* poll_publisher.cxx + + A publication of data of type poll + + This file is derived from code automatically generated by the rtiddsgen + command: + +rtiddsgen -language C++ -example poll.idl + + Example publication of type poll automatically generated by + 'rtiddsgen'. To test them follow these steps: + +(1) Compile this file and the example subscription. + + (2) Start the subscription with the command + objs//poll_subscriber + + (3) Start the publication with the command + objs//poll_publisher + + (4) [Optional] Specify the list of discovery initial peers and + multicast receive addresses via an environment variable or a file + (in the current working directory) called NDDS_DISCOVERY_PEERS. + + You can run any number of publishers and subscribers programs, and can + add and remove them dynamically from the domain. + + + Example: + +To run the example application on domain : + +On Unix: + +objs//poll_publisher o + objs//poll_subscriber + + On Windows: + +objs\\poll_publisher + objs\\poll_subscriber + + +modification history +------------ ------- +*/ + +#include +#include +#ifdef RTI_VX653 +#include +#endif +#include "poll.h" +#include "pollSupport.h" +#include "ndds/ndds_cpp.h" + +/* Delete all entities */ +static int publisher_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ + /* + + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + status = -1; + } + */ + + return status; +} + +extern "C" int publisher_main(int domainId, int sample_count) +{ + DDSDomainParticipant *participant = NULL; + DDSPublisher *publisher = NULL; + DDSTopic *topic = NULL; + DDSDataWriter *writer = NULL; + pollDataWriter * poll_writer = NULL; + poll *instance = NULL; + DDS_ReturnCode_t retcode; + DDS_InstanceHandle_t instance_handle = DDS_HANDLE_NIL; + const char *type_name = NULL; + int count = 0; + DDS_Duration_t send_period = {4,0}; + + /* To customize participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize publisher QoS, use + the configuration file USER_QOS_PROFILES.xml */ + publisher = participant->create_publisher( + DDS_PUBLISHER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (publisher == NULL) { + printf("create_publisher error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Register type before creating topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + publisher_shutdown(participant); + return -1; + } + + /* To customize topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize data writer QoS, use + the configuration file USER_QOS_PROFILES.xml */ + writer = publisher->create_datawriter( + topic, DDS_DATAWRITER_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (writer == NULL) { + printf("create_datawriter error\n"); + publisher_shutdown(participant); + return -1; + } + poll_writer = pollDataWriter::narrow(writer); + if (poll_writer == NULL) { + printf("DataWriter narrow error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Create data sample for writing */ + instance = pollTypeSupport::create_data(); + if (instance == NULL) { + printf("pollTypeSupport::create_data error\n"); + publisher_shutdown(participant); + return -1; + } + + /* For a data type that has a key, if the same instance is going to be + written multiple times, initialize the key here + and register the keyed instance prior to writing */ + /* + instance_handle = poll_writer->register_instance(*instance); + */ + + /* Main loop */ + for (count=0; (sample_count == 0) || (count < sample_count); ++count) { + + printf("Writing poll, count %d\n", count); + + /* Modify the data to be sent here */ + + retcode = poll_writer->write(*instance, instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("write error %d\n", retcode); + } + + NDDSUtility::sleep(send_period); + } + + /* + retcode = poll_writer->unregister_instance( + *instance, instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("unregister instance error %d\n", retcode); + } + */ + + /* Delete data sample */ + retcode = pollTypeSupport::delete_data(instance); + if (retcode != DDS_RETCODE_OK) { + printf("pollTypeSupport::delete_data error %d\n", retcode); + } + + /* Delete all entities */ + return publisher_shutdown(participant); +} + +#if defined(RTI_WINCE) +int wmain(int argc, wchar_t** argv) +{ + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = _wtoi(argv[1]); + } + if (argc >= 3) { + sample_count = _wtoi(argv[2]); + } + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return publisher_main(domainId, sample_count); +} + +#elif !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) +int main(int argc, char *argv[]) +{ + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = atoi(argv[1]); + } + if (argc >= 3) { + sample_count = atoi(argv[2]); + } + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return publisher_main(domainId, sample_count); +} +#endif + +#ifdef RTI_VX653 +const unsigned char* __ctype = *(__ctypePtrGet()); + +extern "C" void usrAppInit () +{ + #ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ + #endif + + /* add application specific code here */ + taskSpawn("pub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)publisher_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +} +#endif + diff --git a/realtime_connext/poll_subscriber.cxx b/realtime_connext/poll_subscriber.cxx new file mode 100644 index 0000000..aae517d --- /dev/null +++ b/realtime_connext/poll_subscriber.cxx @@ -0,0 +1,305 @@ + +/* poll_subscriber.cxx + + A subscription example + + This file is derived from code automatically generated by the rtiddsgen + command: + +rtiddsgen -language C++ -example poll.idl + + Example subscription of type poll automatically generated by + 'rtiddsgen'. To test them follow these steps: + +(1) Compile this file and the example publication. + + (2) Start the subscription with the command + objs//poll_subscriber + + (3) Start the publication with the command + objs//poll_publisher + + (4) [Optional] Specify the list of discovery initial peers and + multicast receive addresses via an environment variable or a file + (in the current working directory) called NDDS_DISCOVERY_PEERS. + + You can run any number of publishers and subscribers programs, and can + add and remove them dynamically from the domain. + + + Example: + +To run the example application on domain : + +On Unix: + +objs//poll_publisher + objs//poll_subscriber + + On Windows: + +objs\\poll_publisher + objs\\poll_subscriber + + +modification history +------------ ------- +*/ + +#include +#include +#ifdef RTI_VX653 +#include +#endif +#include "poll.h" +#include "pollSupport.h" +#include "ndds/ndds_cpp.h" + +class pollListener : public DDSDataReaderListener { + public: + virtual void on_requested_deadline_missed( + DDSDataReader* /*reader*/, + const DDS_RequestedDeadlineMissedStatus& /*status*/) {} + + virtual void on_requested_incompatible_qos( + DDSDataReader* /*reader*/, + const DDS_RequestedIncompatibleQosStatus& /*status*/) {} + + virtual void on_sample_rejected( + DDSDataReader* /*reader*/, + const DDS_SampleRejectedStatus& /*status*/) {} + + virtual void on_liveliness_changed( + DDSDataReader* /*reader*/, + const DDS_LivelinessChangedStatus& /*status*/) {} + + virtual void on_sample_lost( + DDSDataReader* /*reader*/, + const DDS_SampleLostStatus& /*status*/) {} + + virtual void on_subscription_matched( + DDSDataReader* /*reader*/, + const DDS_SubscriptionMatchedStatus& /*status*/) {} + + virtual void on_data_available(DDSDataReader* reader); +}; + +void pollListener::on_data_available(DDSDataReader* reader) +{ + pollDataReader *poll_reader = NULL; + pollSeq data_seq; + DDS_SampleInfoSeq info_seq; + DDS_ReturnCode_t retcode; + int i; + + poll_reader = pollDataReader::narrow(reader); + if (poll_reader == NULL) { + printf("DataReader narrow error\n"); + return; + } + + retcode = poll_reader->take( + data_seq, info_seq, DDS_LENGTH_UNLIMITED, + DDS_ANY_SAMPLE_STATE, DDS_ANY_VIEW_STATE, DDS_ANY_INSTANCE_STATE); + + if (retcode == DDS_RETCODE_NO_DATA) { + return; + } else if (retcode != DDS_RETCODE_OK) { + printf("take error %d\n", retcode); + return; + } + + for (i = 0; i < data_seq.length(); ++i) { + if (info_seq[i].valid_data) { + pollTypeSupport::print_data(&data_seq[i]); + } + } + + retcode = poll_reader->return_loan(data_seq, info_seq); + if (retcode != DDS_RETCODE_OK) { + printf("return loan error %d\n", retcode); + } +} + +/* Delete all entities */ +static int subscriber_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides the finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ + /* + + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + status = -1; + } + */ + return status; +} + +extern "C" int subscriber_main(int domainId, int sample_count) +{ + DDSDomainParticipant *participant = NULL; + DDSSubscriber *subscriber = NULL; + DDSTopic *topic = NULL; + pollListener *reader_listener = NULL; + DDSDataReader *reader = NULL; + DDS_ReturnCode_t retcode; + const char *type_name = NULL; + int count = 0; + DDS_Duration_t receive_period = {4,0}; + int status = 0; + + /* To customize the participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the subscriber QoS, use + the configuration file USER_QOS_PROFILES.xml */ + subscriber = participant->create_subscriber( + DDS_SUBSCRIBER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (subscriber == NULL) { + printf("create_subscriber error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Register the type before creating the topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Create a data reader listener */ + reader_listener = new pollListener(); + + /* To customize the data reader QoS, use + the configuration file USER_QOS_PROFILES.xml */ + reader = subscriber->create_datareader( + topic, DDS_DATAREADER_QOS_DEFAULT, reader_listener, + DDS_STATUS_MASK_ALL); + if (reader == NULL) { + printf("create_datareader error\n"); + subscriber_shutdown(participant); + delete reader_listener; + return -1; + } + + /* Main loop */ + for (count=0; (sample_count == 0) || (count < sample_count); ++count) { + + printf("poll subscriber sleeping for %d sec...\n", + receive_period.sec); + + NDDSUtility::sleep(receive_period); + } + + /* Delete all entities */ + status = subscriber_shutdown(participant); + delete reader_listener; + + return status; +} + +#if defined(RTI_WINCE) +int wmain(int argc, wchar_t** argv) +{ + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = _wtoi(argv[1]); + } + if (argc >= 3) { + sample_count = _wtoi(argv[2]); + } + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return subscriber_main(domainId, sample_count); +} + +#elif !(defined(RTI_VXWORKS) && !defined(__RTP__)) && !defined(RTI_PSOS) +int main(int argc, char *argv[]) +{ + int domainId = 0; + int sample_count = 0; /* infinite loop */ + + if (argc >= 2) { + domainId = atoi(argv[1]); + } + if (argc >= 3) { + sample_count = atoi(argv[2]); + } + + /* Uncomment this to turn on additional logging + NDDSConfigLogger::get_instance()-> + set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, + NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL); + */ + + return subscriber_main(domainId, sample_count); +} +#endif + +#ifdef RTI_VX653 +const unsigned char* __ctype = *(__ctypePtrGet()); + +extern "C" void usrAppInit () +{ + #ifdef USER_APPL_INIT + USER_APPL_INIT; /* for backwards compatibility */ + #endif + + /* add application specific code here */ + taskSpawn("sub", RTI_OSAPI_THREAD_PRIORITY_NORMAL, 0x8, 0x150000, (FUNCPTR)subscriber_main, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +} +#endif diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx new file mode 100644 index 0000000..8209394 --- /dev/null +++ b/realtime_connext/poll_utils.cxx @@ -0,0 +1,468 @@ +#ifndef EXAMPLE_POLL_UTILS_H +#define EXAMPLE_POLL_UTILS_H + +#include +#include +#include + +#ifdef RTI_VX653 +#include +#endif +#include "poll.h" +#include "pollSupport.h" +#include "ndds/ndds_cpp.h" + +#include + +unsigned int samples_received = 0; + +struct PublisherNode +{ + pollDataWriter * poll_writer; + poll *instance; + DDS_InstanceHandle_t instance_handle; + int count; + unsigned int message_length; +}; + +struct Arguments +{ + int argc; + char **argv; +}; + +/* Delete all entities */ +static int subscriber_shutdown( + DDSDomainParticipant *participant) +{ + printf("Samples received by subscriber: %d\n", samples_received); + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides the finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ + /* + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + //status = -1; + } + */ + return status; +} + +void *subscriber_callback(void *args) +{ + pollDataReader *poll_reader = static_cast(args); + DDS_SampleInfoSeq info_seq; + pollSeq data_seq; + + /* Check for new data calling the DataReader's take() method */ + DDS_ReturnCode_t retcode = poll_reader->take( + data_seq, info_seq, DDS_LENGTH_UNLIMITED, + DDS_ANY_SAMPLE_STATE, DDS_ANY_VIEW_STATE, DDS_ANY_INSTANCE_STATE); + if (retcode == DDS_RETCODE_NO_DATA) { + /// Not an error + return NULL; + } else if (retcode != DDS_RETCODE_OK) { + // Is an error + printf("take error: %d\n", retcode); + exit(-1); + } + + int len = 0; + double sum = 0; + + /* Iterate through the samples read using the take() method, getting + * the number of samples got and, adding the value of x on each of + * them to calculate the average afterwards. */ + for (int i = 0; i < data_seq.length(); ++i) { + if (!info_seq[i].valid_data) + continue; + len ++; + sum += data_seq[i].seq; + ++samples_received; + } + + /* + if (len > 0) + printf("Got %d samples. Avg = %.1f\n", len, sum/len); + */ + + retcode = poll_reader->return_loan(data_seq, info_seq); + if (retcode != DDS_RETCODE_OK) { + printf("return loan error %d\n", retcode); + } + +} + +int subscriber_main(int argc, char *argv[]) +{ + rttest_read_args(argc, argv); + + int domainId = 0; + DDSDomainParticipant *participant = NULL; + DDSSubscriber *subscriber = NULL; + DDSTopic *topic = NULL; + DDSDataReader *reader = NULL; + DDS_ReturnCode_t retcode; + const char *type_name = NULL; + int count = 0; + /* Poll for new samples every 5 seconds */ + DDS_Duration_t receive_period = {5,0}; + int status = 0; + + /* To customize the participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the subscriber QoS, use + the configuration file USER_QOS_PROFILES.xml */ + subscriber = participant->create_subscriber( + DDS_SUBSCRIBER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (subscriber == NULL) { + printf("create_subscriber error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Register the type before creating the topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + subscriber_shutdown(participant); + return -1; + } + + /* To customize the topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* Call create_datareader passing NULL in the listener parameter */ + reader = subscriber->create_datareader( + topic, DDS_DATAREADER_QOS_DEFAULT, NULL, + DDS_STATUS_MASK_ALL); + if (reader == NULL) { + printf("create_datareader error\n"); + subscriber_shutdown(participant); + return -1; + } + + /* If you want to change datareader_qos.history.kind programmatically rather + * than using the XML file, you will need to add the following lines to your + * code and comment out the create_datareader call above. */ + + /* + DDS_DataReaderQos datareader_qos; + retcode = subscriber->get_default_datareader_qos(datareader_qos); + if (retcode != DDS_RETCODE_OK) { + printf("get_default_datareader_qos error\n"); + return -1; + } + + datareader_qos.history.kind = DDS_KEEP_ALL_HISTORY_QOS; + + reader = subscriber->create_datareader( + topic, datareader_qos, NULL, + DDS_STATUS_MASK_ALL); + if (reader == NULL) { + printf("create_datareader error\n"); + subscriber_shutdown(participant); + return -1; + } + */ + + pollDataReader *poll_reader = pollDataReader::narrow(reader); + if (poll_reader == NULL) { + printf("DataReader narrow error\n"); + return -1; + } + + if (rttest_set_sched_priority(97, SCHED_RR) != 0) { + perror("Failed to set scheduling priority"); + } + + if (rttest_lock_memory() != 0) { + perror("Couldn't lock memory"); + } + rttest_prefault_stack(); + + /* Main loop */ + rttest_spin(subscriber_callback, static_cast(poll_reader)); + + /* Delete all entities */ + status = subscriber_shutdown(participant); + + rttest_write_results_file("rttest_subscriber_results"); + rttest_finish(); + + return status; +} + +int subscriber_main(Arguments *args) +{ + return subscriber_main(args->argc, args->argv); +} + +void *subscriber_main(void *args) +{ + Arguments *new_args = static_cast(args); + int ret = subscriber_main(new_args); + return static_cast(&ret); +} + +/* Delete all entities */ +static int publisher_shutdown( + DDSDomainParticipant *participant) +{ + DDS_ReturnCode_t retcode; + int status = 0; + + if (participant != NULL) { + retcode = participant->delete_contained_entities(); + if (retcode != DDS_RETCODE_OK) { + printf("delete_contained_entities error %d\n", retcode); + status = -1; + } + + retcode = DDSTheParticipantFactory->delete_participant(participant); + if (retcode != DDS_RETCODE_OK) { + printf("delete_participant error %d\n", retcode); + status = -1; + } + } + + /* RTI Connext provides finalize_instance() method on + domain participant factory for people who want to release memory used + by the participant factory. Uncomment the following block of code for + clean destruction of the singleton. */ + retcode = DDSDomainParticipantFactory::finalize_instance(); + if (retcode != DDS_RETCODE_OK) { + printf("finalize_instance error %d\n", retcode); + //status = -1; + } + + return status; +} + +void *publisher_callback(void *args) +{ + PublisherNode *pub_node = static_cast(args); + // message instance, instance_handle, poll_writer + /* Set x to a random number between 0 and 9 */ + pub_node->instance->seq = (int)(rand()/(RAND_MAX/10.0)); + for (int j = 0; j < pub_node->message_length; j++) { + pub_node->instance->content[j] = pub_node->count; + } + + DDS_ReturnCode_t retcode = pub_node->poll_writer->write(*pub_node->instance, pub_node->instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("write error %d\n", retcode); + } + ++pub_node->count; +} + +int publisher_main(int argc, char *argv[]) +{ + unsigned int message_length = 1; + { + int c; + // l stands for message length + opterr = 0; + optind = 1; + int argc_copy = argc; + char *argv_copy[argc]; + for (int i = 0; i < argc; ++i) + { + size_t len = strlen(argv[i]); + argv_copy[i] = (char*) malloc(len); + memcpy(argv_copy[i], argv[i], len); + } + + while ((c = getopt(argc_copy, argv_copy, "l:")) != -1) + { + switch(c) + { + case 'l': + message_length = std::stoul(std::string(optarg)); + break; + default: + break; + } + } + } + + rttest_read_args(argc, argv); + int domainId = 0; + DDSDomainParticipant *participant = NULL; + DDSPublisher *publisher = NULL; + DDSTopic *topic = NULL; + DDSDataWriter *writer = NULL; + pollDataWriter * poll_writer = NULL; + poll *instance = NULL; + DDS_ReturnCode_t retcode; + DDS_InstanceHandle_t instance_handle = DDS_HANDLE_NIL; + const char *type_name = NULL; + int count = 0; + + /* To customize participant QoS, use + the configuration file USER_QOS_PROFILES.xml */ + participant = DDSTheParticipantFactory->create_participant( + domainId, DDS_PARTICIPANT_QOS_DEFAULT, + NULL /* listener */, DDS_STATUS_MASK_NONE); + if (participant == NULL) { + printf("create_participant error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize publisher QoS, use + the configuration file USER_QOS_PROFILES.xml */ + publisher = participant->create_publisher( + DDS_PUBLISHER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); + if (publisher == NULL) { + printf("create_publisher error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Register type before creating topic */ + type_name = pollTypeSupport::get_type_name(); + retcode = pollTypeSupport::register_type( + participant, type_name); + if (retcode != DDS_RETCODE_OK) { + printf("register_type error %d\n", retcode); + publisher_shutdown(participant); + return -1; + } + + /* To customize topic QoS, use + the configuration file USER_QOS_PROFILES.xml */ + topic = participant->create_topic( + "Example poll", + type_name, DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (topic == NULL) { + printf("create_topic error\n"); + publisher_shutdown(participant); + return -1; + } + + /* To customize data writer QoS, use + the configuration file USER_QOS_PROFILES.xml */ + writer = publisher->create_datawriter( + topic, DDS_DATAWRITER_QOS_DEFAULT, NULL /* listener */, + DDS_STATUS_MASK_NONE); + if (writer == NULL) { + printf("create_datawriter error\n"); + publisher_shutdown(participant); + return -1; + } + poll_writer = pollDataWriter::narrow(writer); + if (poll_writer == NULL) { + printf("DataWriter narrow error\n"); + publisher_shutdown(participant); + return -1; + } + + /* Create data sample for writing */ + + instance = pollTypeSupport::create_data(); + + if (instance == NULL) { + printf("pollTypeSupport::create_data error\n"); + publisher_shutdown(participant); + return -1; + } + strcpy(instance->content, std::string(message_length, '.').c_str()); + + /* For a data type that has a key, if the same instance is going to be + written multiple times, initialize the key here + and register the keyed instance prior to writing */ + instance_handle = poll_writer->register_instance(*instance); + + PublisherNode pub_node; + pub_node.instance = instance; + pub_node.instance_handle = instance_handle; + pub_node.poll_writer = poll_writer; + pub_node.count = 0; + pub_node.message_length = message_length; + + /* Initialize random seed before entering the loop */ + // srand(time(NULL)); + + if (rttest_set_sched_priority(98, SCHED_RR) != 0) { + perror("Failed to set scheduling priority"); + } + + if (rttest_lock_memory() != 0) { + perror("Couldn't lock memory"); + } + rttest_prefault_stack(); + + rttest_spin(publisher_callback, static_cast(&pub_node)); + rttest_write_results_file("rttest_publisher_results"); + rttest_finish(); + + retcode = poll_writer->unregister_instance( + *instance, instance_handle); + if (retcode != DDS_RETCODE_OK) { + printf("unregister instance error %d\n", retcode); + } + + /* Delete data sample */ + retcode = pollTypeSupport::delete_data(instance); + if (retcode != DDS_RETCODE_OK) { + printf("pollTypeSupport::delete_data error %d\n", retcode); + } + + /* Delete all entities */ + return publisher_shutdown(participant); +} + +int publisher_main(Arguments *args) +{ + return publisher_main(args->argc, args->argv); +} + +void *publisher_main(void *args) +{ + Arguments *new_args = static_cast(args); + int ret = publisher_main(new_args); + return static_cast(&ret); +} + +#endif From 988ef6dd621f45bf13b626a875bac718e7690241 Mon Sep 17 00:00:00 2001 From: Jackie Kay Date: Wed, 15 Jul 2015 14:01:07 -0700 Subject: [PATCH 34/34] clean up --- realtime_connext/build.sh | 2 +- realtime_connext/poll_utils.cxx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/realtime_connext/build.sh b/realtime_connext/build.sh index 484d63d..5509f1e 100644 --- a/realtime_connext/build.sh +++ b/realtime_connext/build.sh @@ -4,5 +4,5 @@ rtiddsgen2 poll.idl -replace -language C++ -example x64Linux3.xgcc4.6.3 mkdir build cd build -cmake .. +cmake .. $@ make diff --git a/realtime_connext/poll_utils.cxx b/realtime_connext/poll_utils.cxx index 8209394..2c7df1a 100644 --- a/realtime_connext/poll_utils.cxx +++ b/realtime_connext/poll_utils.cxx @@ -128,7 +128,7 @@ int subscriber_main(int argc, char *argv[]) DDS_Duration_t receive_period = {5,0}; int status = 0; - /* To customize the participant QoS, use + /* To customize the participant QoS, use the configuration file USER_QOS_PROFILES.xml */ participant = DDSTheParticipantFactory->create_participant( domainId, DDS_PARTICIPANT_QOS_DEFAULT, @@ -139,7 +139,7 @@ int subscriber_main(int argc, char *argv[]) return -1; } - /* To customize the subscriber QoS, use + /* To customize the subscriber QoS, use the configuration file USER_QOS_PROFILES.xml */ subscriber = participant->create_subscriber( DDS_SUBSCRIBER_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE); @@ -240,8 +240,8 @@ int subscriber_main(Arguments *args) void *subscriber_main(void *args) { Arguments *new_args = static_cast(args); - int ret = subscriber_main(new_args); - return static_cast(&ret); + subscriber_main(new_args); + return NULL; } /* Delete all entities */ @@ -283,7 +283,7 @@ void *publisher_callback(void *args) PublisherNode *pub_node = static_cast(args); // message instance, instance_handle, poll_writer /* Set x to a random number between 0 and 9 */ - pub_node->instance->seq = (int)(rand()/(RAND_MAX/10.0)); + pub_node->instance->seq = pub_node->count; for (int j = 0; j < pub_node->message_length; j++) { pub_node->instance->content[j] = pub_node->count; }