DDS::Streams::StreamDataWriter_impl::StreamDataWriter_impl(
    DDS::Publisher_ptr publisher_in,
    DDS::DomainId_t domainId,
    DDS::Streams::StreamDataWriterQos &qos_in,
    DDS::TypeSupport_ptr typeSupport,
    const char *streamName)
{
    DDS::DomainParticipant_var myParticipant;
    DDS::Publisher_var myPublisher;
    DDS::String_var typeName;
    DDS::ReturnCode_t result;

    assert(typeSupport);
    assert(streamName);
    assert(domainId);

    if(!publisher_in) {
        os_mutexLock(&classLock.lfMutex);
        if (this->nrParticipantUsers == 0) {
            myParticipant = DDS::DomainParticipantFactory::get_instance()->create_participant(domainId, PARTICIPANT_QOS_DEFAULT, NULL, 0);
            if (myParticipant) {
                this->participant = myParticipant;
                nrParticipantUsers = 1;
            } else {
                OS_REPORT(OS_ERROR, "DDS::Streams::StreamDataWriter_impl", 0, "Failed to create internal participant");
                os_mutexUnlock(&classLock.lfMutex);
                throw StreamsException("Failed to create internal participant. Is the domain running?", DDS::RETCODE_PRECONDITION_NOT_MET);
            }
        } else {
            myParticipant = this->participant;
            nrParticipantUsers++;
        }
        myPublisher = myParticipant->create_publisher(DDS::Streams::default_publisher_qos, NULL, 0);
        if (myPublisher) {
            publisher = myPublisher;
        } else {
            OS_REPORT(OS_ERROR, "DDS::Streams::StreamDataWriter_impl", 0, "Failed to create internal publisher");
            os_mutexUnlock(&classLock.lfMutex);
            throw StreamsException("Failed to create internal publisher", DDS::RETCODE_PRECONDITION_NOT_MET);
        }
        os_mutexUnlock(&classLock.lfMutex);
    } else {
        publisher = NULL;
        myParticipant = publisher_in->get_participant();
        if (myParticipant == NULL) {
            OS_REPORT(OS_ERROR, "DDS::Streams::StreamDataWriter_impl", 0, "Failed to get participant");
            throw StreamsException("Failed to get participant. Is the domain running?", DDS::RETCODE_PRECONDITION_NOT_MET);
        }
    }

    typeName = typeSupport->get_type_name();
    result = typeSupport->register_type(myParticipant, typeName);
    /* TypeSupport is released here because caller is the parent constructor which cannot release it in the member init list */
    release(typeSupport);
    if (result != DDS::RETCODE_OK) {
        OS_REPORT(OS_ERROR, "DDS::Streams::StreamDataWriter_impl", 0, "Failed to register streams topic for type %s", typeName.in());
        throw StreamsException("Failed to register streams topic", result);
    }

    topic = myParticipant->create_topic(streamName, typeName, DDS::Streams::default_topic_qos, NULL, 0);
    if (!topic.in()) {
        OS_REPORT(OS_ERROR, "DDS::Streams::StreamDataWriter_impl", 0, "Failed to create topic %s", streamName);
        throw StreamsException("Failed to create streams topic", result);
    }

    /* Check if QoS is valid */
    if ((qos_in.flush.max_delay.sec < 0) ||
        ((qos_in.flush.max_delay.sec == 0) &&
        (qos_in.flush.max_delay.nanosec == 0))) {
        throw StreamsException("Invalid QoS: auto-flush delay is not a valid duration", DDS::RETCODE_BAD_PARAMETER);
    } else if ((qos_in.flush.max_samples <= 0) ||
            (qos_in.flush.max_samples == DDS::LENGTH_UNLIMITED)) {
        throw StreamsException("Invalid QoS: auto-flush sample limit must be a positive number and cannot be DDS::LENGTH_UNLIMITED", DDS::RETCODE_BAD_PARAMETER);
    } else {
        qos = qos_in;
    }
}
int OSPL_MAIN (int argc, char *argv[])
{
  // usage : ContentFilteredTopicDataSubscriber <subscription_string>
  const char *ContentFilteredTopicDataToSubscribe;
  os_time delay_200ms = { 0, 200000000 };
  char buf[MAX_MSG_LEN];

  if (argc > 1)
  {
    ContentFilteredTopicDataToSubscribe = argv[1];
  }
  else
  {
    cerr <<
      "*** [ContentFilteredTopicDataSubscriber] Subscription string not specified" <<
      endl;
    cerr << "*** usage : ContentFilteredTopicDataSubscriber <subscription_string>" <<
      endl;
    return  - 1;
  }

  StockSeq msgList;
  SampleInfoSeq infoSeq;

  DDSEntityManager mgr;

  // create domain participant
  char partition_name[] = "ContentFilteredTopic example";
  mgr.createParticipant(partition_name);

  //create type
  StockTypeSupport_var st = new StockTypeSupport();
  mgr.registerType(st.in());

  //create Topic
  char topic_name[] = "StockTrackerExclusive";
  mgr.createTopic(topic_name);

  //create Subscriber
  mgr.createSubscriber();

  char sTopicName[] = "MyStockTopic";
  // create subscription filter
  snprintf(buf, MAX_MSG_LEN, "ticker = '%s'", ContentFilteredTopicDataToSubscribe);
  DDS::String_var sFilter = DDS::string_dup(buf);
  // Filter expr
  StringSeq sSeqExpr;
  sSeqExpr.length(0);
  // create topic
  mgr.createContentFilteredTopic(sTopicName, sFilter.in(), sSeqExpr);
  // create Filtered DataReader
  cout << "=== [ContentFilteredTopicDataSubscriber] Subscription filter : " << sFilter
    << endl;
  mgr.createReader(true);

  DataReader_var dreader = mgr.getReader();
  StockDataReader_var ContentFilteredTopicDataReader = StockDataReader::_narrow(dreader.in());
  checkHandle(ContentFilteredTopicDataReader.in(), "StockDataReader::_narrow");

  cout << "=== [ContentFilteredTopicDataSubscriber] Ready ..." << endl;

  bool closed = false;
  ReturnCode_t status =  - 1;
  int count = 0;
  while (!closed && count < 1500) // We dont want the example to run indefinitely
  {
    status = ContentFilteredTopicDataReader->take(msgList, infoSeq, LENGTH_UNLIMITED,
      ANY_SAMPLE_STATE, ANY_VIEW_STATE, ANY_INSTANCE_STATE);
    checkStatus(status, "ContentFilteredTopicDataDataReader::take");
    for (DDS::ULong i = 0; i < msgList.length(); i++)
    {
        if(infoSeq[i].valid_data)
        {
           if (msgList[i].price ==  - 1.0f)
           {
              closed = true;
              break;
           }
        }
     cout << "=== [ContentFilteredTopicDataSubscriber] receives stockQuote :  ("<< msgList[i].ticker << ", " << msgList[i].price << ')'<< endl;
    }

    status = ContentFilteredTopicDataReader->return_loan(msgList, infoSeq);
    checkStatus(status, "StockDataReader::return_loan");
    os_nanoSleep(delay_200ms);
    ++count;
  }

  cout << "=== [ContentFilteredTopicDataSubscriber] Market Closed" << endl;

  //cleanup
  mgr.deleteReader(ContentFilteredTopicDataReader.in ());
  mgr.deleteSubscriber();
  mgr.deleteFilteredTopic();
  mgr.deleteTopic();
  mgr.deleteParticipant();

  return 0;
}