/* Sleeper thread: sleeps 60 seconds and then triggers the WaitSet. */ void * delayedEscape( void *arg) { DDS_ReturnCode_t status; sleep(60); /* wait for 60 sec. */ status = DDS_GuardCondition_set_trigger_value(escape, TRUE); checkStatus(status, "DDS_GuardCondition_set_trigger_value"); return NULL; }
int OSPL_MAIN (int argc, char *argv[]) { DDS_sequence_ListenerData_Msg* message_seq = DDS_sequence_ListenerData_Msg__alloc(); DDS_SampleInfoSeq* message_infoSeq = DDS_SampleInfoSeq__alloc(); DDS_Subscriber message_Subscriber; DDS_DataReader message_DataReader; DDS_WaitSet waitSet; DDS_ConditionSeq* guardList = NULL; struct DDS_DataReaderListener *message_Listener; DDS_Duration_t timeout = { 0, 200000000 }; struct Listener_data* Listener_data; DDS_GuardCondition guardCondition = DDS_GuardCondition__alloc(); int count = 0; DDS_StatusMask mask; // Create DDS DomainParticipant createParticipant("Listener example"); // Register the Topic's type in the DDS Domain. g_MessageTypeSupport = ListenerData_MsgTypeSupport__alloc(); checkHandle(g_MessageTypeSupport, "ListenerData_MsgTypeSupport__alloc"); registerMessageType(g_MessageTypeSupport); // Create the Topic's in the DDS Domain. g_MessageTypeName = ListenerData_MsgTypeSupport_get_type_name(g_MessageTypeSupport); g_MessageTopic = createTopic("ListenerData_Msg", g_MessageTypeName); DDS_free(g_MessageTypeName); DDS_free(g_MessageTypeSupport); // Create the Subscriber's in the DDS Domain. message_Subscriber = createSubscriber(); // Request a Reader from the the Subscriber. message_DataReader = createDataReader(message_Subscriber, g_MessageTopic); /* Allocate the DataReaderListener interface. */ message_Listener = DDS_DataReaderListener__alloc(); checkHandle(message_Listener, "DDS_DataReaderListener__alloc"); Listener_data = malloc(sizeof(struct Listener_data)); checkHandle(Listener_data, "malloc"); Listener_data->guardCondition = &guardCondition; Listener_data->message_DataReader = &message_DataReader; Listener_data->isClosed = &isClosed; message_Listener->listener_data = Listener_data; message_Listener->on_data_available = on_data_available; message_Listener->on_requested_deadline_missed = on_requested_deadline_missed; mask = DDS_DATA_AVAILABLE_STATUS | DDS_REQUESTED_DEADLINE_MISSED_STATUS; g_status = DDS_DataReader_set_listener(message_DataReader, message_Listener, mask); checkStatus(g_status, "DDS_DataReader_set_listener"); // WaitSet is used to avoid spinning in the loop below. waitSet = DDS_WaitSet__alloc(); checkHandle(waitSet, "DDS_WaitSet__alloc"); g_status = DDS_WaitSet_attach_condition(waitSet, guardCondition); checkStatus(g_status, "DDS_WaitSet_attach_condition (readCondition)"); // Initialize and pre-allocate the GuardList used to obtain the triggered Conditions. guardList = DDS_ConditionSeq__alloc(); checkHandle(guardList, "DDS_ConditionSeq__alloc"); guardList->_maximum = 1; guardList->_length = 0; guardList->_buffer = DDS_ConditionSeq_allocbuf(1); checkHandle(guardList->_buffer, "DDS_ConditionSeq_allocbuf"); printf("\n=== [ListenerDataSubscriber] Ready..."); isClosed = FALSE; do { g_status = DDS_WaitSet_wait(waitSet, guardList, &timeout); if(g_status != DDS_RETCODE_TIMEOUT) { checkStatus(g_status, "DDS_WaitSet_wait"); } else { printf("\n=== [ListenerDataSubscriber] (timeout)"); } g_status = DDS_GuardCondition_set_trigger_value(guardCondition, FALSE); checkStatus(g_status, "DDS_GuardCondition_set_trigger_value"); ++ count; } while( isClosed == FALSE && count < 1500 ); printf("\n\n=== [ListenerDataSubscriber] isClosed"); // Cleanup DDS from the created Entities. deleteDataReader(message_Subscriber, message_DataReader); deleteSubscriber(message_Subscriber); deleteTopic(g_MessageTopic); deleteParticipant(); // Cleanup C allocations // Recursively free the instances sequence using the OpenSplice API. DDS_free(message_seq); DDS_free(message_infoSeq); free(Listener_data); // Print out an empty line, just to avoid the shell writing on the same line as our last output. printf("\n"); return 0; }
int OSPL_MAIN (int argc, char *argv[]) { DDS_sequence_WaitSetData_Msg* message_seq = DDS_sequence_WaitSetData_Msg__alloc(); DDS_SampleInfoSeq* message_infoSeq = DDS_SampleInfoSeq__alloc(); DDS_Subscriber message_Subscriber; DDS_DataReader message_DataReader; DDS_char* query_parameter = "Hello again"; DDS_char *query_string = "message=%0"; DDS_ReadCondition readCondition; DDS_QueryCondition queryCondition; DDS_StatusCondition statusCondition; DDS_WaitSet waitSet; DDS_GuardCondition escape; DDS_LivelinessChangedStatus livelinessChangedStatus; DDS_ConditionSeq *guardList = NULL; DDS_Duration_t timeout = { 20, 0 }; int count = 0; DDS_long previousLivelinessCount; c_bool isClosed = FALSE; c_bool isEscaped = FALSE; c_bool writerLeft = FALSE; unsigned long i, j; // Create DDS DomainParticipant createParticipant("WaitSet example"); // Register the Topic's type in the DDS Domain. g_MessageTypeSupport = WaitSetData_MsgTypeSupport__alloc(); checkHandle(g_MessageTypeSupport, "WaitSetData_MsgTypeSupport__alloc"); registerMessageType(g_MessageTypeSupport); // Create the Topic's in the DDS Domain. g_MessageTypeName = WaitSetData_MsgTypeSupport_get_type_name(g_MessageTypeSupport); g_MessageTopic = createTopic("WaitSetData_Msg", g_MessageTypeName); DDS_free(g_MessageTypeName); DDS_free(g_MessageTypeSupport); // Create the Subscriber's in the DDS Domain. message_Subscriber = createSubscriber(); // Request a Reader from the the Subscriber. message_DataReader = createDataReader(message_Subscriber, g_MessageTopic); // 1- Create a ReadCondition that will contain new Msg only. readCondition = DDS_DataReader_create_readcondition(message_DataReader, DDS_NOT_READ_SAMPLE_STATE, DDS_NEW_VIEW_STATE, DDS_ALIVE_INSTANCE_STATE); checkHandle(readCondition, "DDS_DataReader_create_readcondition (newUser)"); // 2- Create QueryCondition. queryCondition = createQueryCondition(message_DataReader, query_string, (DDS_char*) query_parameter); printf("=== [WaitSetDataSubscriber] Query : message = \"%s\"", query_parameter); // 3- Obtain a StatusCondition associated to a Writer // and that triggers only when the Writer changes Liveliness. statusCondition = DDS_DataReader_get_statuscondition(message_DataReader); checkHandle(statusCondition, "DDS_DataReader_get_statuscondition"); g_status = DDS_StatusCondition_set_enabled_statuses(statusCondition, DDS_LIVELINESS_CHANGED_STATUS); checkStatus(g_status, "DDS_StatusCondition_set_enabled_statuses"); // 4- Create a GuardCondition which will be used to close the subscriber. escape = DDS_GuardCondition__alloc(); checkHandle(escape, "DDS_GuardCondition__alloc"); // Create a waitset and add the 4 Conditions created above : // ReadCondition, QueryCondition, StatusCondition, GuardCondition. waitSet = DDS_WaitSet__alloc(); checkHandle(waitSet, "DDS_WaitSet__alloc"); g_status = DDS_WaitSet_attach_condition(waitSet, readCondition); checkStatus(g_status, "DDS_WaitSet_attach_condition (readCondition)"); g_status = DDS_WaitSet_attach_condition(waitSet, queryCondition); checkStatus(g_status, "DDS_WaitSet_attach_condition (queryCondition)"); g_status = DDS_WaitSet_attach_condition(waitSet, statusCondition); checkStatus(g_status, "DDS_WaitSet_attach_condition (statusCondition)"); g_status = DDS_WaitSet_attach_condition(waitSet, escape); checkStatus(g_status, "DDS_WaitSet_attach_condition (escape)"); // Initialize and pre-allocate the GuardList used to obtain the triggered Conditions. guardList = DDS_ConditionSeq__alloc(); checkHandle(guardList, "DDS_ConditionSeq__alloc"); guardList->_maximum = 4; guardList->_length = 0; guardList->_buffer = DDS_ConditionSeq_allocbuf(4); checkHandle(guardList->_buffer, "DDS_ConditionSeq_allocbuf"); printf("\n=== [WaitSetDataSubscriber] Ready ..."); // Used to store the livelinessChangedStatus.alive_count value (StatusCondition). previousLivelinessCount = 0; do { // Wait until at least one of the Conditions in the waitset triggers. g_status = DDS_WaitSet_wait(waitSet, guardList, &timeout); if (g_status == DDS_RETCODE_OK) { i = 0; do { if( guardList->_buffer[i] == statusCondition ) { // StatusCondition triggered. // Some liveliness has changed (either a DataWriter joined or a DataWriter left). // Check whether a new Writer appeared. g_status = DDS_DataReader_get_liveliness_changed_status(message_DataReader, &livelinessChangedStatus); checkStatus(g_status, "DDS_DataReader_get_liveliness_changed_status"); if( livelinessChangedStatus.alive_count > previousLivelinessCount ) { // a DataWriter joined. printf("\n\n!!! a MsgWriter joined"); g_status = DDS_StatusCondition_set_enabled_statuses(statusCondition, DDS_LIVELINESS_CHANGED_STATUS); checkStatus(g_status, "DDS_StatusCondition_set_enabled_statuses"); } else if( livelinessChangedStatus.alive_count < previousLivelinessCount ) { // A MsgWriter lost its liveliness. printf("\n\n!!! a MsgWriter lost its liveliness"); g_status = DDS_StatusCondition_set_enabled_statuses(statusCondition, DDS_LIVELINESS_CHANGED_STATUS); checkStatus(g_status, "DDS_StatusCondition_set_enabled_statuses"); writerLeft = TRUE; printf("\n === Triggering escape condition"); g_status = DDS_GuardCondition_set_trigger_value(escape, TRUE); checkStatus(g_status, "DDS_GuardCondition_set_trigger_value"); } else if ( livelinessChangedStatus.alive_count == previousLivelinessCount ) { // The status has changed, though alive_count is still zero, // this implies that both events have occurred, // and that the value is back to zero already. printf("\n\n!!! a MsgWriter joined\n"); printf("\n\n!!! a MsgWriter lost its liveliness\n"); writerLeft = TRUE; printf("\n === Triggering escape condition"); g_status = DDS_GuardCondition_set_trigger_value(escape, TRUE); checkStatus(g_status, "DDS_GuardCondition_set_trigger_value"); // NB: we do not need to activate this Condition anymore; // both events occurred. } // NB: Here we record the count a in order to compare it next time this condition triggers (?). previousLivelinessCount = livelinessChangedStatus.alive_count; } else if( guardList->_buffer[i] == readCondition ) { /* The newMsg ReadCondition contains data */ g_status = WaitSetData_MsgDataReader_read_w_condition(message_DataReader, message_seq, message_infoSeq, DDS_LENGTH_UNLIMITED, readCondition); checkStatus(g_status, "WaitSetData_MsgDataReader_read_w_condition"); for( j = 0; j < message_seq->_length ; j++ ) { printf("\n --- New message received ---"); if( message_infoSeq->_buffer[j].valid_data == TRUE ) { printf("\n userID : %d", message_seq->_buffer[j].userID); printf("\n Message : \"%s\"", message_seq->_buffer[j].message); } else { printf("\n Data is invalid!"); } } fflush(stdout); g_status = WaitSetData_MsgDataReader_return_loan(message_DataReader, message_seq, message_infoSeq); checkStatus(g_status, "WaitSetData_MsgDataReader_return_loan"); } else if( guardList->_buffer[i] == queryCondition ) { /* The queryCond QueryCondition contains data */ g_status = WaitSetData_MsgDataReader_take_w_condition(message_DataReader, message_seq, message_infoSeq, DDS_LENGTH_UNLIMITED, queryCondition); checkStatus(g_status, "WaitSetData_MsgDataReader_take_w_condition"); for( j = 0; j < message_seq->_length ; j++ ) { printf("\n\n --- message received (with QueryCOndition on message field) ---"); if( message_infoSeq->_buffer[j].valid_data == TRUE ) { printf("\n userID : %d", message_seq->_buffer[j].userID); printf("\n Message : \"%s\"", message_seq->_buffer[j].message); } else { printf("\n Data is invalid!"); } } fflush(stdout); g_status = WaitSetData_MsgDataReader_return_loan(message_DataReader, message_seq, message_infoSeq); checkStatus(g_status, "WaitSetData_MsgDataReader_return_loan"); } // This checks whether the Timeout Thread has resumed waiting. else if( guardList->_buffer[i] == escape ) { printf("\n escape condition triggered! - count = %d\n ", count); isEscaped = TRUE; g_status = DDS_GuardCondition_set_trigger_value(escape, FALSE); checkStatus(g_status, "DDS_GuardCondition_set_trigger_value"); } } while( ++i < guardList->_length ); } else if (g_status != DDS_RETCODE_TIMEOUT) { // DDS_RETCODE_TIMEOUT is considered as an error // only after it has occurred count times checkStatus(g_status, "DDS_WaitSet_wait"); } else { printf("!!! [INFO] WaitSet timedout - count = %d\n ", count); } ++count; isClosed = isEscaped && writerLeft; } while( isClosed == FALSE && count < 20); if (count >= 20) { printf( "*** Error : Timed out - count = %d ***\n", count); } /* Remove all Conditions from the WaitSet. */ g_status = DDS_WaitSet_detach_condition(waitSet, escape); checkStatus(g_status, "DDS_WaitSet_detach_condition (escape)"); g_status = DDS_WaitSet_detach_condition(waitSet, statusCondition); checkStatus(g_status, "DDS_WaitSet_detach_condition (statusCondition)"); g_status = DDS_WaitSet_detach_condition(waitSet, queryCondition); checkStatus(g_status, "DDS_WaitSet_detach_condition (queryCondition)"); g_status = DDS_WaitSet_detach_condition(waitSet, readCondition); checkStatus(g_status, "DDS_WaitSet_detach_condition (readCondition)"); // Cleanup DDS from the created Entities. deleteQueryCondition(message_DataReader, readCondition); deleteQueryCondition(message_DataReader, queryCondition); deleteDataReader(message_Subscriber, message_DataReader); deleteSubscriber(message_Subscriber); deleteTopic(g_MessageTopic); deleteParticipant(); // Cleanup C allocations // Recursively free the instances sequence using the OpenSplice API. DDS_free(guardList); DDS_free(message_seq); DDS_free(message_infoSeq); DDS_free(waitSet); DDS_free(escape); printf("\n"); return 0; }