### Navigation

- index
- next |
- previous |
- Modeling Guide »

# 11. Appendix B

This appendix contains the example, user-written C++ source code included with the Vortex OpenSplice Modeler `Chatroom` C++ example. The Chatroom system is the example used in the Tutorial.

There are two different versions of some of the Chatroom’s C++ modules, one version for Linux, the other for Windows, in order to accommodate differences between these platforms.

The source code is given in the following order:

Chatter Application:

> ChatterApplication.cpp, Linux Version

> ChatterApplication.cpp, Windows Version

MessageBoard Application:

> MessageBoardApplication.cpp, Linux Version

> MessageBoardApplication.cpp, Windows Version

> ChatMessageDataReaderListenerImpl.h, Linux version

> ChatMessageDataReaderListenerImpl.h, Windows version

> ChatMessageDataReaderListenerImpl.cpp

> NamedMessageDataReaderListenerImpl.h, Linux Version

> NamedMessageDataReaderListenerImpl.h, Windows Version

> NamedMessageDataReaderListenerImpl.cpp

UserLoad Application:

> UserLoadApplication.cpp, Linux Version

> UserLoadApplication.cpp, Windows Version

> CheckStatus.h

> CheckStatus.cpp

## 11.1. Chatroom Example, C++ Source Code

### 11.1.1. Chatter Application

#### 11.1.1.1. ChatterApplication.cpp, Linux Version

    ChatterApplication.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    ChatterApplication.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Example for the C++  programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'ChatterApplication' executable.
     *
     ***/
    #include <string>
    #include <sstream>
    #include <iostream>
    #include <unistd.h>

    #include "ChatterApplication.h"
    #include "CheckStatus.h"

    #define NUM_MSG 10
    #define TERMINATION_MESSAGE -1

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    int main(int argc, char *argv[]) {
       /* Sample definitions */
       ChatMessage *msg; /* Example on Heap */
       NameService ns; /* Example on Stack */

       /* DDS Identifiers */
       InstanceHandle_t userHandle;
       ReturnCode_t status;

       /* Others */
       int ownID = 1;
       char *chatterName= NULL;
       ostringstream buf;

       /* Initialize the application */
       ChatterApplicationWrapperImplementation chatterApplication;

       try {
          chatterApplication.start();
       } catch(WrapperException& e) {
          cout << "Exception occurred while starting the application:" << endl;
          cout << e.what();
          return -1;
       }

       /* Type-specific DDS entities */
       NameServiceDataWriter_ptr nameServer =
             chatterApplication.getParticipantWrapper()->getPublisherWrapper()
                ->getNameServiceDataWriterWrapper()->getDataWriter();
       ChatMessageDataWriter_ptr talker =
             chatterApplication.getParticipantWrapper()->getPublisherWrapper()
                ->getChatMessageDataWriterWrapper()->getDataWriter();

       /* Options: Chatter [ownID [name]] */
       if (argc > 1) {
          istringstream args(argv[1]);
          args >> ownID;
          if (argc > 2) {
             chatterName = argv[2];
          }
       }

       /* Initialize the NameServer attributes */
       ns.userID = ownID;
       if (chatterName) {
          ns.name = string_dup(chatterName);
       } else {
          buf << "Chatter " << ownID;
          ns.name = string_dup(buf.str().c_str() );
       }

       /* Write the user-information into the system
          (registering the instance implicitly). */
       status = nameServer->write(ns, HANDLE_NIL);
       checkStatus(status, "NameServiceDataWriter::write");

       /* Initialize the chat messages on Heap. */
       msg = new ChatMessage();
       checkHandle(msg, "new ChatMessage");
       msg->userID = ownID;
       msg->index = 0;
       buf.str(string("") );
       if (ownID == TERMINATION_MESSAGE) {
          buf << "Termination message.";
       } else {
          buf << "Hi there, I will send you " << NUM_MSG << " more messages.";
       }
       msg->content = string_dup(buf.str().c_str() );
       cout << "Writing message: \"" << msg->content << "\"" << endl;

       /* Register a chat message for this user (pre-allocating resources for it!!) */
       userHandle = talker->register_instance(*msg);

       /* Write a message using the pre-generated instance handle. */
       status = talker->write(*msg, userHandle);
       checkStatus(status, "ChatMessageDataWriter::write");

       sleep(1); /* do not run so fast! */

       /* Write any number of messages,
          re-using the existing string-buffer: no leak!!. */
       for (int i = 1; i <= NUM_MSG && ownID != TERMINATION_MESSAGE; i++) {
          buf.str(string("") );
          msg->index = i;
          buf << "Message no. " << i;
          msg->content = string_dup(buf.str().c_str() );
          cout << "Writing message: \"" << msg->content << "\"" << endl;
          status = talker->write(*msg, userHandle);
          checkStatus(status, "ChatMessageDataWriter::write");
          sleep(1); /* do not run so fast! */
       }

       /* Leave the room by disposing and unregistering the message instance. */
       status = talker->dispose(*msg, userHandle);
       checkStatus(status, "ChatMessageDataWriter::dispose");
       status = talker->unregister_instance(*msg, userHandle);
       checkStatus(status, "ChatMessageDataWriter::unregister_instance");

       /* Also unregister our name. */
       status = nameServer->unregister_instance(ns, HANDLE_NIL);
       checkStatus(status, "NameServiceDataWriter::unregister_instance");

       /* Release the data-samples. */
       delete msg; // msg allocated on heap: explicit de-allocation required!!

       /* stop application */
       try {
          chatterApplication.stop();
       } catch(WrapperException& e) {
          cout << "Exception occurred while stopping the application:" << endl;
          cout << e.what();
          return -1;
       }

       return 0;
    }

#### 11.1.1.2. ChatterApplication.cpp, Windows Version

    ChatterApplication.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    ChatterApplication.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Example for the C++  programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'ChatterApplication' executable.
     *
     ***/
    #include <string>
    #include <sstream>
    #include <iostream>

    #include "ChatterApplication.h"
    #include "CheckStatus.h"

    #define NUM_MSG 10
    #define TERMINATION_MESSAGE -1

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    int main(int argc, char *argv[]) {
       /* Sample definitions */
       ChatMessage *msg; /* Example on Heap */
       NameService ns; /* Example on Stack */

       /* DDS Identifiers */
       InstanceHandle_t userHandle;
       ReturnCode_t status;

       /* Others */
       int ownID = 1;
       char *chatterName= NULL;
       ostringstream buf;

       /* Initialize the application */
       ChatterApplicationWrapperImplementation chatterApplication;

       try {
          chatterApplication.start();
       } catch(WrapperException& e) {
          cout << "Exception occurred while starting the application:" << endl;
          cout << e.what();
          return -1;
       }

       /* Type-specific DDS entities */
       NameServiceDataWriter_ptr nameServer =
             chatterApplication.getParticipantWrapper()->getPublisherWrapper()
             ->getNameServiceDataWriterWrapper()->getDataWriter();
       ChatMessageDataWriter_ptr talker =
             chatterApplication.getParticipantWrapper()->getPublisherWrapper()
             ->getChatMessageDataWriterWrapper()->getDataWriter();

       /* Options: Chatter [ownID [name]] */
       if (argc > 1) {
          istringstream args(argv[1]);
          args >> ownID;
          if (argc > 2) {
             chatterName = argv[2];
          }
       }

       /* Initialize the NameServer attributes */
       ns.userID = ownID;
       if (chatterName) {
          ns.name = string_dup(chatterName);
       } else {
          buf << "Chatter " << ownID;
          ns.name = string_dup(buf.str().c_str() );
       }

       /* Write the user-information into the system
          (registering the instance implicitly). */
       status = nameServer->write(ns, HANDLE_NIL);
       checkStatus(status, "NameServiceDataWriter::write");

       /* Initialize the chat messages on Heap. */
       msg = new ChatMessage();
       checkHandle(msg, "new ChatMessage");
       msg->userID = ownID;
       msg->index = 0;
       buf.str(string("") );
       if (ownID == TERMINATION_MESSAGE) {
          buf << "Termination message.";
       } else {
          buf << "Hi there, I will send you " << NUM_MSG << " more messages.";
       }
       msg->content = string_dup(buf.str().c_str() );
       cout << "Writing message: \"" << msg->content << "\"" << endl;

       /* Register a chat message for this user (pre-allocating resources for it!!) */
       userHandle = talker->register_instance(*msg);

       /* Write a message using the pre-generated instance handle. */
       status = talker->write(*msg, userHandle);
       checkStatus(status, "ChatMessageDataWriter::write");

       sleep(1); /* do not run so fast! */

       /* Write any number of messages,
          re-using the existing string-buffer: no leak!!. */
       for (int i = 1; i <= NUM_MSG && ownID != TERMINATION_MESSAGE; i++) {
          buf.str(string("") );
          msg->index = i;
          buf << "Message no. " << i;
          msg->content = string_dup(buf.str().c_str() );
          cout << "Writing message: \"" << msg->content << "\"" << endl;
          status = talker->write(*msg, userHandle);
          checkStatus(status, "ChatMessageDataWriter::write");
          Sleep(1000); /* do not run so fast! */
       }

       /* Leave the room by disposing and unregistering the message instance. */
       status = talker->dispose(*msg, userHandle);
       checkStatus(status, "ChatMessageDataWriter::dispose");
       status = talker->unregister_instance(*msg, userHandle);
       checkStatus(status, "ChatMessageDataWriter::unregister_instance");

       /* Also unregister our name. */
       status = nameServer->unregister_instance(ns, HANDLE_NIL);
       checkStatus(status, "NameServiceDataWriter::unregister_instance");

       /* Release the data-samples. */
       delete msg; // msg allocated on heap: explicit de-allocation required!!

       /* stop application */
       try {
          chatterApplication.stop();
       } catch(WrapperException& e) {
          cout << "Exception occurred while stopping the application:" << endl;
          cout << e.what();
          return -1;
       }

       return 0;
    }

### 11.1.2. MessageBoard Application

#### 11.1.2.1. MessageBoardApplication.cpp, Linux Version

    MessageBoardApplication.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    MessageBoardApplication.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the
     * 'MessageBoardApplication' executable.
     *
     ***/

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <unistd.h>

    #include "CheckStatus.h"
    #include "MessageBoardApplication.h"

    #include "ChatMessageDataReaderListenerImpl.h"
    #include "NamedMessageDataReaderListenerImpl.h"

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    #define TERMINATION_MESSAGE -1

    int main(int argc, char *argv[]) {
       /* DDS Identifiers */
       string ownID = "0";

       /* Options: MessageBoard [ownID] */
       /* Messages having owner ownID will be ignored */
       if (argc > 1) {
          istringstream args(argv[1]);
          args >> ownID;;
       }

       MessageBoardApplicationWrapperImplementation messageBoardApplication;

       try {
          StringSeq exprParams;
          exprParams.length(1);
          exprParams[0] = DDS::string_dup(ownID.c_str());
          messageBoardApplication.getParticipantWrapper()
             ->getNamedMessageFilteredTopicWrapper()->setExpressionParameters(
             exprParams);
          /* Initialize the application */
          messageBoardApplication.start();
       } catch (WrapperException& e) {
          cout << "Exception occurred while initializing the application:"
                << endl;
          cout << e.what();
          return -1;
       }

       /* Create the listeners for the MessageBoard application */
       ChatMessageDataReaderListenerImpl* chatMessageDataReaderListener =
             new ChatMessageDataReaderListenerImpl(&messageBoardApplication);

       /* put the object in a smart pointer for resource management */
       DDS::DataReaderListener_var chatMessageDataReaderListenerVar(
             chatMessageDataReaderListener);

       NamedMessageDataReaderListenerImpl* namedMessageDataReaderListener =
             new NamedMessageDataReaderListenerImpl(&messageBoardApplication);

       DDS::DataReaderListener_var namedMessageDataReaderListenerVar(
             namedMessageDataReaderListener);

       try {
          /* Attach the ChatMessageDataReaderListener to the ChatMessageDataReader */
          messageBoardApplication.getPrivateParticipantWrapper()
             ->getSubscriberWrapper()->getChatMessageDataReaderWrapper()->attach(
                chatMessageDataReaderListener);

          /* Attach the NamedMessageDataReaderListener to NamedMessageDataReader */
          messageBoardApplication.getParticipantWrapper()->getSubscriberWrapper()
             ->getNamedMessageDataReaderWrapper()->attach(
                namedMessageDataReaderListener);
       } catch (WrapperException& e) {
          cout << "Exception occurred while attaching a listener:" << endl;
          cout << e.what();
          return -1;
       }

       cout
          << "MessageBoard has opened: send ChatMessage with userID = -1 to close it."
          << endl << endl;

       /* Wait for the ChatMessageDataReaderListener to finish */
       while (!chatMessageDataReaderListener->isTerminated()) {
          sleep(1);
       }

       /* Wait for the NamedMessageDataReaderListener to finish */
       while (!namedMessageDataReaderListener->isTerminated()) {
          sleep(1);
       }

       cout << "Termination message received: exiting..." << endl;

       try {
          /* Detach the ChatMessageDataReaderListener to the ChatMessageDataReader */
          messageBoardApplication.getPrivateParticipantWrapper()
             ->getSubscriberWrapper()->getChatMessageDataReaderWrapper()->detach(
                chatMessageDataReaderListener);

          /* Detach the NamedMessageDataReaderListener to the NamedMessageDataReader */
          messageBoardApplication.getParticipantWrapper()->getSubscriberWrapper()
             ->getNamedMessageDataReaderWrapper()->detach(
                namedMessageDataReaderListener);
       } catch (WrapperException& e) {
          cout << "Exception occurred while detaching a listener:" << endl;
          cout << e.what();
          return -1;
       }

       chatMessageDataReaderListener->cleanup();

       try {
          /* Stop the application */
          messageBoardApplication.stop();
       } catch (WrapperException& e) {
          cout << "Exception occurred while stopping the application:" << endl;
          cout << e.what();
          return -1;
       }

       return 0;
    }

#### 11.1.2.2. MessageBoardApplication.cpp, Windows Version

    MessageBoardApplication.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    MessageBoardApplication.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/

    #include <iostream>
    #include <string>
    #include <sstream>

    #include "ccpp_dds_dcps.h"
    #include "CheckStatus.h"
    #include "exported_MessageBoardApplicationDcps.h"
    #include "Chat/MessageBoardApplicationWrapperImplementation.h"
    #include "Chat/NamedMessageFilteredTopicWrapper.h"

    #include "Chat/MessageBoardApplication/ParticipantWrapper.h"
    #include "Chat/MessageBoardApplication/Participant/SubscriberWrapper.h"
    #include "Chat/MessageBoardApplication/Participant/Subscriber/NamedMessageDataReaderWrapper.h"

    #include "Chat/MessageBoardApplication/PrivateParticipantWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/SubscriberWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/Subscriber/ChatMessageDataReaderWrapper.h"

    #include "ChatMessageDataReaderListenerImpl.h"
    #include "NamedMessageDataReaderListenerImpl.h"

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    #define TERMINATION_MESSAGE -1

    int main(int argc, char *argv[])
    {
       /* DDS Identifiers */
       string ownID = "0";

       /* Options: MessageBoard [ownID] */
       /* Messages having owner ownID will be ignored */
       if (argc > 1)
       {
          istringstream args(argv[1]);
          args >> ownID;;
       }

       MessageBoardApplicationWrapperImplementation messageBoardApplication;

       StringSeq exprParams;
       exprParams.length(1);
       exprParams[0] = DDS::string_dup(ownID.c_str());

       messageBoardApplication.getParticipantWrapper()
          ->getNamedMessageFilteredTopicWrapper()->set_expression_parameters(
             exprParams);

       /* Initialize the application */
       messageBoardApplication.start();

       /* Create the listeners for the MessageBoard application */
       ChatMessageDataReaderListenerImpl* chatMessageDataReaderListener =
             new ChatMessageDataReaderListenerImpl(&messageBoardApplication);

       /* put the object in a smart pointer for resource management */
       DDS::DataReaderListener_var
             chatMessageDataReaderListenerVar(chatMessageDataReaderListener);

       NamedMessageDataReaderListenerImpl* namedMessageDataReaderListener =
             new NamedMessageDataReaderListenerImpl(&messageBoardApplication);

       DDS::DataReaderListener_var
             namedMessageDataReaderListenerVar(namedMessageDataReaderListener);

       /* Attach the ChatMessageDataReaderListener to the ChatMessageDataReader */
       ReturnCode_t status = messageBoardApplication.getPrivateParticipantWrapper()
          ->getSubscriberWrapper()->getChatMessageDataReaderWrapper()
          ->set_listener(chatMessageDataReaderListener,
             chatMessageDataReaderListener->getStatusMask());
       checkStatus(status, "Chat::ChatMessageDataReader::set_listener");

       /* Attach the NamedMessageDataReaderListener to the NamedMessageDataReader */
       status = messageBoardApplication.getParticipantWrapper()
          ->getSubscriberWrapper()->getNamedMessageDataReaderWrapper()->getDataReader()
          ->set_listener(namedMessageDataReaderListener,
             namedMessageDataReaderListener->getStatusMask());
       checkStatus(status, "Chat::ChatMessageDataReader::set_listener");

       cout
          << "MessageBoard has opened: send ChatMessage with userID = -1 to close it."
          << endl << endl;

       /* Wait for the ChatMessageDataReaderListener to finish */
       while (!chatMessageDataReaderListener->isTerminated())
       {
          Sleep(1000);
       }

       /* Wait for the NamedMessageDataReaderListener to finish */
       while (!namedMessageDataReaderListener->isTerminated())
       {
          Sleep(1000);
       }

       cout << "Termination message received: exiting..." << endl;

       /* Detach the ChatMessageDataReaderListener to the ChatMessageDataReader */
       messageBoardApplication.getPrivateParticipantWrapper()->getSubscriberWrapper()
          ->set_listener(0, 0);

       /* Detach the NamedMessageDataReaderListener to the NamedMessageDataReader */
       messageBoardApplication.getParticipantWrapper()->getSubscriberWrapper()
          ->set_listener(0, 0);

       chatMessageDataReaderListener->cleanup();

       /* Stop the application */
       messageBoardApplication.stop();

       return 0;
    }

#### 11.1.2.3. ChatMessageDataReaderListenerImpl.h, Linux version

    ChatMessageDataReaderListenerImpl.h

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    ChatMessageDataReaderListenerImpl.h
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/
    #ifndef _CHATMESSAGEDATAREADERLISTENERIMPL_H_
    #define _CHATMESSAGEDATAREADERLISTENERIMPL_H_

    #include <string>

    #include <pthread.h>

    #include "Chat/MessageBoardApplication/ChatMessageDataReaderListener.h"
    #include "Chat/MessageBoardApplicationWrapper.h"
    #include "exported_MessageBoardApplicationDcps.h"

    class ChatMessageDataReaderListenerImpl :
       public Chat::MessageBoardApplication::ChatMessageDataReaderListener
    {
    public:
       ChatMessageDataReaderListenerImpl(
             const Chat::MessageBoardApplicationWrapper* messageBoardApplication);

       void on_data_available(DDS::DataReader_ptr dataReader);
       void cleanup();
       bool isTerminated();

    private:

       class IsTerminated
       {
       public:
          IsTerminated()
          {
             m_isTerminated = false;
             pthread_mutex_init(&m_mutex, 0);
          }

          virtual ~IsTerminated()
          {
             pthread_mutex_destroy(&m_mutex);
          }

          bool isTerminated()
          {
             bool ret;

             pthread_mutex_lock(&m_mutex);
             ret = m_isTerminated;
             pthread_mutex_unlock(&m_mutex);

             return ret;
          }

          void setTerminated(bool isTerminated)
          {
             pthread_mutex_lock(&m_mutex);
             m_isTerminated = isTerminated;
             pthread_mutex_unlock(&m_mutex);
          }

       private:
          pthread_mutex_t m_mutex;
          bool m_isTerminated;
       };

       IsTerminated m_isTerminated;

       static int TERMINATION_MESSAGE;

       const Chat::MessageBoardApplicationWrapper* m_messageBoardApplication;
       Chat::ChatMessageDataReader_ptr m_chatMsgReader;
       Chat::NameServiceDataReader_ptr m_nameServiceReader;
       Chat::NamedMessageDataWriter_ptr m_namedMessageWriter;

       DDS::QueryCondition_ptr m_nameFinder;
       DDS::StringSeq m_nameFinderParams;

       DDS::ReadCondition_ptr m_newMessages;

       int m_previousID;
       DDS::String_mgr m_userName;

    };

    #endif // _CHATMESSAGEDATAREADERLISTENERIMPL_H_

#### 11.1.2.4. ChatMessageDataReaderListenerImpl.h, Windows version

    ChatMessageDataReaderListenerImpl.h

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    ChatMessageDataReaderListenerImpl.h
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/
    #ifndef _CHATMESSAGEDATAREADERLISTENERIMPL_H_
    #define _CHATMESSAGEDATAREADERLISTENERIMPL_H_

    #include <string>
    #include "Chat/MessageBoardApplication/ChatMessageDataReaderListener.h"
    #include "Chat/MessageBoardApplicationWrapper.h"
    #include "exported_MessageBoardApplicationDcps.h"

    class ChatMessageDataReaderListenerImpl :
       public Chat::MessageBoardApplication::ChatMessageDataReaderListener
    {
    public:
       ChatMessageDataReaderListenerImpl(
             const Chat::MessageBoardApplicationWrapper* messageBoardApplication);

       void on_data_available(DDS::DataReader_ptr dataReader);
       void cleanup();
       bool isTerminated();

    private:

       class IsTerminated
       {
       public:
          IsTerminated()
          {
             m_isTerminated = false;
             m_mutex = CreateMutex(NULL, FALSE, NULL);
          }

          virtual ~IsTerminated()
          {
             CloseHandle(m_mutex);
          }

          bool isTerminated()
          {
             bool ret;

             WaitForSingleObject(m_mutex, INFINITE);
             ret = m_isTerminated;
             ReleaseMutex(m_mutex);

             return ret;
          }

          void setTerminated(bool isTerminated)
          {
             WaitForSingleObject(m_mutex, INFINITE);
             m_isTerminated = isTerminated;
             ReleaseMutex(m_mutex);
          }

       private:
          HANDLE m_mutex;
          bool m_isTerminated;
       };

       IsTerminated m_isTerminated;

       static int TERMINATION_MESSAGE;

       const Chat::MessageBoardApplicationWrapper* m_messageBoardApplication;
       Chat::ChatMessageDataReader_ptr m_chatMsgReader;
       Chat::NameServiceDataReader_ptr m_nameServiceReader;
       Chat::NamedMessageDataWriter_ptr m_namedMessageWriter;

       DDS::QueryCondition_ptr m_nameFinder;
       DDS::StringSeq m_nameFinderParams;

       DDS::ReadCondition_ptr m_newMessages;

       int m_previousID;
       DDS::String_mgr m_userName;

    };

    #endif // _CHATMESSAGEDATAREADERLISTENERIMPL_H_

#### 11.1.2.5. ChatMessageDataReaderListenerImpl.cpp

    ChatMessageDataReaderListenerImpl.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    ChatMessageDataReaderListenerImpl.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/
    #include <sstream>

    #include "ChatMessageDataReaderListenerImpl.h"

    #include "ccpp_dds_dcps.h"
    #include "Chat/MessageBoardApplication/PrivateParticipantWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/SubscriberWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/Subscriber/ChatMessageDataReaderWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/Subscriber/NameServiceDataReaderWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/PublisherWrapper.h"
    #include "Chat/MessageBoardApplication/PrivateParticipant/Publisher/NamedMessageDataWriterWrapper.h"
    #include "CheckStatus.h"

    int ChatMessageDataReaderListenerImpl::TERMINATION_MESSAGE = -1;

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    ChatMessageDataReaderListenerImpl::ChatMessageDataReaderListenerImpl(
          const Chat::MessageBoardApplicationWrapper* messageBoardApplication) :
             m_messageBoardApplication(messageBoardApplication),
             m_chatMsgReader(
                   messageBoardApplication->getPrivateParticipantWrapper()
                   ->getSubscriberWrapper()->getChatMessageDataReaderWrapper()
                   ->getDataReader()),
                   m_nameServiceReader(
                   messageBoardApplication->getPrivateParticipantWrapper()
                   ->getSubscriberWrapper()->getNameServiceDataReaderWrapper()
                   ->getDataReader()),
                   m_namedMessageWriter(
                   messageBoardApplication->getPrivateParticipantWrapper()
                   ->getPublisherWrapper()->getNamedMessageDataWriterWrapper()
                   ->getDataWriter()),
                   m_previousID(-1) {
       /* Create a QueryCondition that will look up userName for a specified userID */
       m_nameFinderParams.length(1);
       m_nameFinderParams[0] = string_dup("0");

       m_nameFinder = m_nameServiceReader->create_querycondition(ANY_SAMPLE_STATE,
             ANY_VIEW_STATE, ANY_INSTANCE_STATE, "userID = %0",
             m_nameFinderParams);
       checkHandle(m_nameFinder,
             "Chat::NameServiceDataReader::create_querycondition");

       m_newMessages = m_chatMsgReader->create_readcondition(ANY_SAMPLE_STATE,
             ANY_VIEW_STATE, ANY_INSTANCE_STATE);
       checkHandle(m_newMessages,
             "Chat::ChatMessageDataReader::create_readcondition");

    }

    void ChatMessageDataReaderListenerImpl::on_data_available(
          DDS::DataReader_ptr dataReader) {

       /* Ignore new data if termination message already received */
       if (m_isTerminated.isTerminated()) {
          return;
       }

       bool terminationReceived = false;
       int status;

       if (dataReader == m_chatMsgReader) {
          ChatMessageSeq chatMsgSeq;
          SampleInfoSeq chatMsgInfoSeq;

          status = m_chatMsgReader->take_w_condition(chatMsgSeq, chatMsgInfoSeq,
                LENGTH_UNLIMITED, m_newMessages);
          checkStatus(status, "Chat::ChatMessageDataReader::take_w_condition");

          /* For each message, extract the key-field and find the corresponding name */
          for (unsigned int i = 0; i < chatMsgSeq.length(); i++) {
             NameServiceSeq nameServiceSeq;
             SampleInfoSeq nameServiceInfoSeq;

             /* Set program termination flag if termination message is received */
             if (chatMsgSeq[i].userID == TERMINATION_MESSAGE) {
                terminationReceived = true;
                break;
             }

             /* Find the corresponding named message */
             if (chatMsgSeq[i].userID != m_previousID) {
                m_previousID = chatMsgSeq[i].userID;

                ostringstream previousID;
                previousID << m_previousID;
                m_nameFinderParams[0] = string_dup(previousID.str().c_str());

                status = m_nameFinder->set_query_parameters(m_nameFinderParams);
                checkStatus(status,
                      "QueryCondition::set_query_arguments(m_nameFinderParams)");

                status = m_nameServiceReader->read_w_condition(nameServiceSeq,
                      nameServiceInfoSeq, LENGTH_UNLIMITED, m_nameFinder);
                checkStatus(status,
                      "Chat::NameServiceDataReader::read_w_condition");

                if (status == RETCODE_NO_DATA) {
                   ostringstream os;
                   os << "Name not found!! id = " + m_previousID;
                   m_userName = string_dup(os.str().c_str());
                } else {
                   m_userName = nameServiceSeq[0].name;
                }

                /* Release the name sample again */
                status = m_nameServiceReader->return_loan(nameServiceSeq,
                      nameServiceInfoSeq);
                checkStatus(status, "Chat::NameServiceDataReader::return_loan");
             }

             NamedMessage namedMsg;

             /* Write merged Topic with userName instead of userID */

             namedMsg.userName = m_userName;
             namedMsg.userID = m_previousID;
             namedMsg.index = chatMsgSeq[i].index;
             namedMsg.content = chatMsgSeq[i].content;

             if (chatMsgInfoSeq[i].valid_data) {
                status = m_namedMessageWriter->write(namedMsg, HANDLE_NIL);
                checkStatus(status, "Chat::NamedMessageDataWriter::write");
             }
          }

          status = m_chatMsgReader->return_loan(chatMsgSeq, chatMsgInfoSeq);
          checkStatus(status, "Chat::ChatMessageDataReader::return_loan");

          if (terminationReceived) {
             m_isTerminated.setTerminated(true);
          }
       }

    }

    bool ChatMessageDataReaderListenerImpl::isTerminated() {
       return m_isTerminated.isTerminated();
    }

    void ChatMessageDataReaderListenerImpl::cleanup() {
       /* Remove all Read Conditions from the DataReaders */

       int status = m_nameServiceReader->delete_readcondition(m_nameFinder);
       checkStatus(status,
             "Chat::NameServiceDataReader::delete_readcondition(nameFinder)");

       status = m_chatMsgReader->delete_readcondition(m_newMessages);
       checkStatus(status,
             "Chat::ChatMessageDataReader::delete_readcondition(newMessages)");

    }

#### 11.1.2.6. NamedMessageDataReaderListenerImpl.h, Linux Version

    NamedMessageDataReaderListenerImpl.h

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    NamedMessageDataReaderListenerImpl.h
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/
    #ifndef _NAMEDMESSAGEDATAREADERLISTENERIMPL_H_
    #define _NAMEDMESSAGEDATAREADERLISTENERIMPL_H_

    #include <pthread.h>

    #include "exported_MessageBoardApplicationDcps.h"
    #include "Chat/MessageBoardApplicationWrapper.h"
    #include "Chat/MessageBoardApplication/NamedMessageDataReaderListener.h"

    class NamedMessageDataReaderListenerImpl : public Chat::MessageBoardApplication::NamedMessageDataReaderListener
    {
    public:
       NamedMessageDataReaderListenerImpl(const Chat::MessageBoardApplicationWrapper* messageBoardApplication);
       void on_data_available (DDS::DataReader_ptr dataReader);
       bool isTerminated();

    private:
       class IsTerminated
       {
       public:
          IsTerminated()
          {
             m_isTerminated = true;
             pthread_mutex_init(&m_mutex, 0);
          }

          virtual ~IsTerminated()
          {
             pthread_mutex_destroy(&m_mutex);
          }

          bool isTerminated()
          {
             bool ret;

             pthread_mutex_lock(&m_mutex);
             ret = m_isTerminated;
             pthread_mutex_unlock(&m_mutex);

             return ret;
          }

          void setTerminated(bool isTerminated)
          {
             pthread_mutex_lock(&m_mutex);
             m_isTerminated = isTerminated;
             pthread_mutex_unlock(&m_mutex);
          }

       private:
          pthread_mutex_t m_mutex;
          bool m_isTerminated;
       };

       IsTerminated m_isTerminated;

       const Chat::MessageBoardApplicationWrapper* m_messageBoardApplication;

       Chat::NamedMessageDataReader_ptr m_namedMsgReader;
    };

    #endif // _NAMEDMESSAGEDATAREADERLISTENERIMPL_H_

#### 11.1.2.7. NamedMessageDataReaderListenerImpl.h, Windows Version

    NamedMessageDataReaderListenerImpl.h

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    NamedMessageDataReaderListenerImpl.h
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/
    #ifndef _NAMEDMESSAGEDATAREADERLISTENERIMPL_H_
    #define _NAMEDMESSAGEDATAREADERLISTENERIMPL_H_

    #include <Windows.h>

    #include "exported_MessageBoardApplicationDcps.h"
    #include "Chat/MessageBoardApplicationWrapper.h"
    #include "Chat/MessageBoardApplication/NamedMessageDataReaderListener.h"

    class NamedMessageDataReaderListenerImpl : public Chat::MessageBoardApplication::NamedMessageDataReaderListener
    {
    public:
       NamedMessageDataReaderListenerImpl(const Chat::MessageBoardApplicationWrapper* messageBoardApplication);
       void on_data_available (DDS::DataReader_ptr dataReader);
       bool isTerminated();

    private:
          class IsTerminated
       {
       public:
          IsTerminated()
          {
             m_isTerminated = false;
             m_mutex = CreateMutex(NULL, FALSE, NULL);
          }

          virtual ~IsTerminated()
          {
             CloseHandle(m_mutex);
          }

          bool isTerminated()
          {
             bool ret;

             WaitForSingleObject(m_mutex, INFINITE);
             ret = m_isTerminated;
             ReleaseMutex(m_mutex);

             return ret;
          }

          void setTerminated(bool isTerminated)
          {
             WaitForSingleObject(m_mutex, INFINITE);
             m_isTerminated = isTerminated;
             ReleaseMutex(m_mutex);
          }

       private:
          HANDLE m_mutex;
          bool m_isTerminated;
       };

       IsTerminated m_isTerminated;

       const Chat::MessageBoardApplicationWrapper* m_messageBoardApplication;

       Chat::NamedMessageDataReader_ptr m_namedMsgReader;
    };

    #endif // _NAMEDMESSAGEDATAREADERLISTENERIMPL_H_

#### 11.1.2.8. NamedMessageDataReaderListenerImpl.cpp

    NamedMessageDataReaderListenerImpl.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    NamedMessageDataReaderListenerImpl.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'MessageBoard' executable.
     *
     ***/
    #include <iostream>

    #include "NamedMessageDataReaderListenerImpl.h"

    #include "Chat/MessageBoardApplication/ParticipantWrapper.h"
    #include "Chat/MessageBoardApplication/Participant/SubscriberWrapper.h"
    #include "Chat/MessageBoardApplication/Participant/Subscriber/NamedMessageDataReaderWrapper.h"

    #include "CheckStatus.h"

    using namespace DDS;
    using namespace Chat;
    using namespace std;

    NamedMessageDataReaderListenerImpl::NamedMessageDataReaderListenerImpl(
          const Chat::MessageBoardApplicationWrapper* messageBoardApplication) :
             m_messageBoardApplication(messageBoardApplication),
             m_namedMsgReader(messageBoardApplication->getParticipantWrapper()->getSubscriberWrapper()->getNamedMessageDataReaderWrapper()->getDataReader())
    {
       m_isTerminated.setTerminated(true);
    }

    void NamedMessageDataReaderListenerImpl::on_data_available(
          DDS::DataReader_ptr dataReader)
    {
       NamedMessageSeq namedMsgSeq;
       DDS::SampleInfoSeq infoSeq;

       m_isTerminated.setTerminated(false);

       int status = m_namedMsgReader->take(namedMsgSeq, infoSeq, LENGTH_UNLIMITED,
             NOT_READ_SAMPLE_STATE, ANY_VIEW_STATE, ALIVE_INSTANCE_STATE);
       checkStatus(status, "Chat::NamedMessageDataReader::read");

       /* For each message, print the message */
       for (unsigned int i = 0; i < namedMsgSeq.length(); i++)
       {
          cout << namedMsgSeq[i].userName << ": " << namedMsgSeq[i].content << endl;
       }

       status = m_namedMsgReader->return_loan(namedMsgSeq, infoSeq);
       checkStatus(status, "Chat::NamedMessageDataReader::return_loan");

       m_isTerminated.setTerminated(true);
    }

    bool NamedMessageDataReaderListenerImpl::isTerminated()
    {
       return m_isTerminated.isTerminated();
    }

### 11.1.3. UserLoad Application

#### 11.1.3.1. UserLoadApplication.cpp, Linux Version

    UserLoadApplication.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    UserLoadApplication.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'UserLoadApplication' executable.
     *
     ***/

    #include <iostream>
    #include <sstream>
    #include <unistd.h>
    #include <string.h>
    #include <pthread.h>
    #include <assert.h>

    #include "UserLoadApplication.h"
    #include "CheckStatus.h"

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    /* entities required by all threads. */
    static DDS::GuardCondition_ptr escape;

    /* 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 = escape->set_trigger_value(TRUE);
       checkStatus(status, "DDS::GuardCondition::set_trigger_value");

       return NULL;
    }

    int main(int argc, char *argv[]) {
       /* DDS Identifiers */
       ReturnCode_t status;
       ConditionSeq guardList;

       ChatMessageSeq msgList;
       NameServiceSeq nsList;
       SampleInfoSeq infoSeq;
       SampleInfoSeq infoSeq2;

       /* Others */
       StringSeq args;

       bool closed = false;
       Long prevCount = 0;
       pthread_t tid;

       UserLoadApplicationWrapperImplementation userLoadApplication;

       /* Initialize the Query Arguments. */
       args.length(1);
       args[0UL] = "0";

       try {
          userLoadApplication.getQueryConditionWrapper()->setQueryParameters(args);

          /* Initialize the application */
          userLoadApplication.start();
       } catch(WrapperException& e) {
          cout << "Error while initializing the application:" << endl;
          cout << e.what() << endl;
          return -1;
       }

       try {
          /* start the WaitSet */
          userLoadApplication.getUserLoadWaitSetWrapper()->start();
       } catch(WrapperException& e) {
          cout << "Error while starting the WaitSet:" << endl;
          cout << e.what() << endl;
          userLoadApplication.stop();
          return -1;
       }

       WaitSet_ptr userLoadWS = userLoadApplication.getUserLoadWaitSetWrapper()->getWaitSet();

       /* Generic DDS entities */
       LivelinessChangedStatus         livChangStatus;

       escape = userLoadApplication.getGuardConditionWrapper()->getCondition();

       /* Type-specific DDS entities */
       NameServiceDataReader_ptr nameServer = userLoadApplication.getParticipantWrapper()->getSubscriberWrapper()->getNameServiceDataReaderWrapper()->getDataReader();
       ChatMessageDataReader_ptr loadAdmin = userLoadApplication.getParticipantWrapper()->getSubscriberWrapper()->getChatMessageDataReaderWrapper()->getDataReader();
       QueryCondition_ptr singleUser = userLoadApplication.getQueryConditionWrapper()->getCondition();
        ReadCondition_ptr newUser = userLoadApplication.getReadConditionWrapper()->getCondition();
        StatusCondition_ptr leftUser = userLoadApplication.getStatusConditionWrapper()->getCondition();

        /* Initialize and pre-allocate the GuardList used to obtain the triggered Conditions. */
        guardList.length(3);

        /* Remove all known Users that are not currently active. */
        status = nameServer->take(
            nsList,
            infoSeq,
            LENGTH_UNLIMITED,
            ANY_SAMPLE_STATE,
            ANY_VIEW_STATE,
            NOT_ALIVE_INSTANCE_STATE);
        checkStatus(status, "Chat::NameServiceDataReader::take");
        status = nameServer->return_loan(nsList, infoSeq);
        checkStatus(status, "Chat::NameServiceDataReader::return_loan");

       /* Start the sleeper thread */
       pthread_create (&tid, NULL, delayedEscape, NULL);

       while (!closed) {
          /* Wait until at least one of the Conditions in the waitset triggers. */
          status = userLoadWS->wait(guardList, DURATION_INFINITE);
          checkStatus(status, "DDS::WaitSet::wait");

          /* Walk over all guards to display information */
          for (ULong i = 0; i < guardList.length(); i++) {
             if (guardList[i].in() == newUser ) {
                /* The newUser ReadCondition contains data */
                status = nameServer->read_w_condition(nsList, infoSeq,
                      LENGTH_UNLIMITED, newUser );
                checkStatus(status,
                      "Chat::NameServiceDataReader::read_w_condition");

                for (ULong j = 0; j < nsList.length(); j++) {
                   cout << "New user: " << nsList[j].name << endl;
                }
                status = nameServer->return_loan(nsList, infoSeq);
                checkStatus(status, "Chat::NameServiceDataReader::return_loan");

             } else if (guardList[i].in() == leftUser ) {
                /* Some liveliness has changed (either a DataWriter joined or a DataWriter left) */
                status
                      = loadAdmin->get_liveliness_changed_status(livChangStatus);
                checkStatus(status,
                      "DDS::DataReader::get_liveliness_changed_status");

                if (livChangStatus.alive_count < prevCount) {
                   /* A user has left the ChatRoom, since a DataWriter lost its liveliness */
                   /* Take the effected users so tey will not appear in the list later on. */

                   status = nameServer->take(nsList, infoSeq,
                         LENGTH_UNLIMITED, ANY_SAMPLE_STATE, ANY_VIEW_STATE,
                         NOT_ALIVE_INSTANCE_STATE);
                   checkStatus(status, "Chat::NameServiceDataReader::take");

                   for (ULong j = 0; j < nsList.length(); j++) {
                      /* re-apply query arguments */
                      ostringstream numberString;
                      numberString << nsList[j].userID;
                      args[0UL] = numberString.str().c_str();
                      status = singleUser->set_query_parameters(args);
                      checkStatus(status,
                            "DDS::QueryCondition::set_query_parameters");

                      /* Read this users history */
                      status = loadAdmin->take_w_condition(msgList, infoSeq2,
                            LENGTH_UNLIMITED, singleUser );
                      checkStatus(status,
                            "Chat::ChatMessageDataReader::take_w_condition");

                      /* Display the user and his history */
                      cout << "Departed user " << nsList[j].name
                            << " has sent " << msgList.length()
                            << " messages." << endl;
                      status = loadAdmin->return_loan(msgList, infoSeq2);
                      checkStatus(status,
                            "Chat::ChatMessageDataReader::return_loan");
                   }
                   status = nameServer->return_loan(nsList, infoSeq);
                   checkStatus(status,
                         "Chat::NameServiceDataReader::return_loan");
                }
                prevCount = livChangStatus.alive_count;

             } else if (guardList[i].in() == escape) {
                cout << "UserLoad has terminated." << endl;
                closed = true;
             } else {
                assert(0);
             };
          } /* for */
       } /* while (!closed) */

       try {
          /* Stop the application */
          userLoadApplication.stop ();
       } catch(WrapperException& e) {
          cout << "Error while stopping the application:" << endl;
          cout << e.what() << endl;
          return -1;
       }

       return 0;
    }

#### 11.1.3.2. UserLoadApplication.cpp, Windows Version

    UserLoadApplication.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    UserLoadApplication.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the 'UserLoadApplication' executable.
     *
     ***/

    #include <iostream>
    #include <sstream>
    #include <string.h>
    #include <assert.h>

    #include "UserLoadApplication.h"
    #include "CheckStatus.h"

    using namespace std;
    using namespace DDS;
    using namespace Chat;

    /* entities required by all threads. */
    static DDS::GuardCondition_ptr escape;

    /* Sleeper thread: sleeps 60 seconds and then triggers the WaitSet. */
    DWORD WINAPI
    delayedEscape(
        LPVOID arg)
    {
        DDS::ReturnCode_t status;

        Sleep(60000);     /* wait for 60 sec. */
        status = escape->set_trigger_value(TRUE);
        checkStatus(status, "DDS::GuardCondition::set_trigger_value");

        return 0;
    }

    int main(int argc, char *argv[]) {
       /* DDS Identifiers */
       ReturnCode_t status;
       ConditionSeq guardList;

       ChatMessageSeq msgList;
       NameServiceSeq nsList;
       SampleInfoSeq infoSeq;
       SampleInfoSeq infoSeq2;

       /* Others */
       StringSeq args;

       bool closed = false;
       Long prevCount = 0;
       DWORD tid;
       HANDLE tHandle = INVALID_HANDLE_VALUE;

       UserLoadApplicationWrapperImplementation userLoadApplication;

       /* Initialize the Query Arguments. */
       args.length(1);
       args[0UL] = "0";

       try {
          userLoadApplication.getQueryConditionWrapper()->setQueryParameters(args);

          /* Initialize the application */
          userLoadApplication.start();
       } catch(WrapperException& e) {
          cout << "Error while initializing the application:" << endl;
          cout << e.what() << endl;
          return -1;
       }

       try {
          /* start the WaitSet */
          userLoadApplication.getUserLoadWaitSetWrapper()->start();
       } catch(WrapperException& e) {
          cout << "Error while starting the WaitSet:" << endl;
          cout << e.what() << endl;
          userLoadApplication.stop();
          return -1;
       }

       WaitSet_ptr userLoadWS = userLoadApplication.getUserLoadWaitSetWrapper()->getWaitSet();

       /* Generic DDS entities */
       LivelinessChangedStatus         livChangStatus;

       escape = userLoadApplication.getGuardConditionWrapper()->getCondition();

       /* Type-specific DDS entities */
       NameServiceDataReader_ptr nameServer = userLoadApplication.getParticipantWrapper()->getSubscriberWrapper()->getNameServiceDataReaderWrapper()->getDataReader();
       ChatMessageDataReader_ptr loadAdmin = userLoadApplication.getParticipantWrapper()->getSubscriberWrapper()->getChatMessageDataReaderWrapper()->getDataReader();
       QueryCondition_ptr singleUser = userLoadApplication.getQueryConditionWrapper()->getCondition();
       ReadCondition_ptr newUser = userLoadApplication.getReadConditionWrapper()->getCondition();
       StatusCondition_ptr leftUser = userLoadApplication.getStatusConditionWrapper()->getCondition();

       /* Initialize and pre-allocate the GuardList used to obtain the triggered Conditions. */
       guardList.length(3);

       /* Remove all known Users that are not currently active. */
       status = nameServer->take(
           nsList,
           infoSeq,
           LENGTH_UNLIMITED,
           ANY_SAMPLE_STATE,
           ANY_VIEW_STATE,
           NOT_ALIVE_INSTANCE_STATE);
       checkStatus(status, "Chat::NameServiceDataReader::take");
       status = nameServer->return_loan(nsList, infoSeq);
       checkStatus(status, "Chat::NameServiceDataReader::return_loan");

       /* Start the sleeper thread */
       tHandle = CreateThread(NULL, 0, delayedEscape, NULL, 0, &tid);

       while (!closed) {
          /* Wait until at least one of the Conditions in the waitset triggers. */
          status = userLoadWS->wait(guardList, DURATION_INFINITE);
          checkStatus(status, "DDS::WaitSet::wait");

          /* Walk over all guards to display information */
          for (ULong i = 0; i < guardList.length(); i++) {
             if (guardList[i].in() == newUser ) {
                /* The newUser ReadCondition contains data */
                status = nameServer->read_w_condition(nsList, infoSeq,
                      LENGTH_UNLIMITED, newUser );
                checkStatus(status,
                      "Chat::NameServiceDataReader::read_w_condition");

                for (ULong j = 0; j < nsList.length(); j++) {
                   cout << "New user: " << nsList[j].name << endl;
                }
                status = nameServer->return_loan(nsList, infoSeq);
                checkStatus(status, "Chat::NameServiceDataReader::return_loan");

             } else if (guardList[i].in() == leftUser ) {
                /* Some liveliness has changed (either a DataWriter joined or a DataWriter left) */
                status
                      = loadAdmin->get_liveliness_changed_status(livChangStatus);
                checkStatus(status,
                      "DDS::DataReader::get_liveliness_changed_status");

                if (livChangStatus.alive_count < prevCount) {
                   /* A user has left the ChatRoom, since a DataWriter lost its liveliness */
                   /* Take the effected users so tey will not appear in the list later on. */

                   status = nameServer->take(nsList, infoSeq,
                         LENGTH_UNLIMITED, ANY_SAMPLE_STATE, ANY_VIEW_STATE,
                         NOT_ALIVE_INSTANCE_STATE);
                   checkStatus(status, "Chat::NameServiceDataReader::take");

                   for (ULong j = 0; j < nsList.length(); j++) {
                      /* re-apply query arguments */
                      ostringstream numberString;
                      numberString << nsList[j].userID;
                      args[0UL] = numberString.str().c_str();
                      status = singleUser->set_query_parameters(args);
                      checkStatus(status,
                            "DDS::QueryCondition::set_query_parameters");

                      /* Read this users history */
                      status = loadAdmin->take_w_condition(msgList, infoSeq2,
                            LENGTH_UNLIMITED, singleUser );
                      checkStatus(status,
                            "Chat::ChatMessageDataReader::take_w_condition");

                      /* Display the user and his history */
                      cout << "Departed user " << nsList[j].name
                            << " has sent " << msgList.length()
                            << " messages." << endl;
                      status = loadAdmin->return_loan(msgList, infoSeq2);
                      checkStatus(status,
                            "Chat::ChatMessageDataReader::return_loan");
                   }
                   status = nameServer->return_loan(nsList, infoSeq);
                   checkStatus(status,
                         "Chat::NameServiceDataReader::return_loan");
                }
                prevCount = livChangStatus.alive_count;

             } else if (guardList[i].in() == escape) {
                cout << "UserLoad has terminated." << endl;
                closed = true;
             } else {
                assert(0);
             };
          } /* for */
       } /* while (!closed) */

       try {
          /* Stop the application */
          userLoadApplication.stop ();
       } catch(WrapperException& e) {
          cout << "Error while stopping the application:" << endl;
          cout << e.what() << endl;
          return -1;
       }

       CloseHandle(tHandle);

       return 0;
    }

#### 11.1.3.3. CheckStatus.h

    CheckStatus.h

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    CheckStatus.h
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the headers for the error handling operations.
     *
     ***/

    #ifndef __CHECKSTATUS_H__
    #define __CHECKSTATUS_H__

    #include "ccpp_dds_dcps.h"
    #include <iostream>

    /**
     * Returns the name of an error code.
     **/
    char *getErrorName(DDS::ReturnCode_t status);

    /**
     * Check the return status for errors. If there is an error, then terminate.
     **/
    void checkStatus(DDS::ReturnCode_t status, const char *info);

    /**
     * Check whether a valid handle has been returned. If not, then terminate.
     **/
    void checkHandle(void *handle, char *info);

    #endif

#### 11.1.3.4. CheckStatus.cpp

    CheckStatus.cpp

    /************************************************************************
     *
     * Copyright (c) 2012 to 2018
     * ADLINK Technology Limited
     * All rights Reserved.
     *
     * LOGICAL_NAME:    CheckStatus.cpp
     * FUNCTION:        Vortex OpenSplice Modeler Tutorial example code.
     * MODULE:          Tutorial for the C++ programming language.
     * DATE             January 2012.
     ************************************************************************
     *
     * This file contains the implementation for the error handling operations.
     *
     ***/

    #include "CheckStatus.h"

    using namespace std;

    /* Array to hold the names for all ReturnCodes. */
    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" };

    /**
     * Returns the name of an error code.
     **/
    char *getErrorName(DDS::ReturnCode_t status)
    {
        return RetCodeName[status];
    }

    /**
     * Check the return status for errors. If there is an error, then terminate.
     **/
    void checkStatus(
        DDS::ReturnCode_t status,
        const char *info ) {

        if (status != DDS::RETCODE_OK && status != DDS::RETCODE_NO_DATA) {
            cerr << "Error in " << info << ": " << getErrorName(status) << endl;
            exit (0);
        }
    }

    /**
     * Check whether a valid handle has been returned. If not, then terminate.
     **/
    void checkHandle(
        void *handle,
        char *info ) {

         if (!handle) {
            cerr << "Error in " << info << ": Creation failed: invalid handle" << endl;
            exit (0);
         }
    }

### Navigation

- index
- next |
- previous |
- Modeling Guide »