FastDDS 源码解析(二十一)创建User的DataWriter(上)

349 阅读11分钟

第一篇 一个例子

车载消息中间件FastDDS 源码解析(一)FastDDS 介绍和使用

第二篇fastdds的组成

车载消息中间件FastDDS 源码解析(二)RtpsParticipant的创建(上)

车载消息中间件FastDDS 源码解析(三)RtpsParticipant的创建(中)

车载消息中间件FastDDS 源码解析(四)RtpsParticipant的创建(下)

车载消息中间件FastDDS 源码解析(五)BuiltinProtocols(上)

车载消息中间件FastDDS 源码解析(六)BuiltinProtocols(中)EDP

车载消息中间件FastDDS 源码解析(七)BuiltinProtocols(下)WLP&TypeLookupManager

车载消息中间件FastDDS 源码解析(八)TimedEvent

车载消息中间件FastDDS 源码解析(九)Message

第三篇组网建立连接

pdp建连

车载消息中间件FastDDS 源码解析(十)发送第一条PDP消息(上)

FastDDS 源码解析(十一)发送第一条PDP消息(中)

FastDDS 源码解析(十二)发送第一条PDP消息(下)---异步发送

FastDDS 源码解析(十三)发送第一条PDP消息---跨进程发送

FastDDS 源码解析(十四)接收PDP消息(上)

FastDDS 源码解析(十五)接收PDP消息(下)

FastDDS 源码解析(十六)处理PDP消息——PDP匹配

EDP建连

FastDDS 源码解析(十七)处理PDP消息——EDP匹配

FastDDS 源码解析(十八)EDP阶段发送心跳heartbeat

FastDDS 源码解析(十九)EDP阶段处理heartbeat消息,发送acknack消息

FastDDS 源码解析(二十)处理acknack消息

之前几篇我们介绍了收到PDP消息之后的EDP协议部分

PDP,EDP,WLP协议都是内置协议,一般都会用到,这个协议是fastdds的基础,在这个协议的基础上我们可以创建用户自己的Writer和Reader,然后才能发送和接收用户自己的消息。

下面我们介绍一下,如何创建用户自己的消息。

1.创建Publisher

参考第一篇车载消息中间件FastDDS 源码解析(一)FastDDS 介绍和使用,我们看到Application在发送消息之前,需要创建自己的自己的Publisher,需要创建自己的topic,创建自己的writer,然后才能发送消息。

我们先看一下创建Publisher的源码

1.1时序图

sequenceDiagram
		participant User
		participant DomainParticipant
		participant DomainParticipantImpl
		participant Publisher
		participant PublisherImpl
		User ->> DomainParticipant: 1.create_publisher
		DomainParticipant ->> DomainParticipantImpl: 2.create_publisher
		DomainParticipantImpl ->> DomainParticipantImpl: 3.create_publisher
		DomainParticipantImpl ->> DomainParticipantImpl: 4.create_publisher_impl
		DomainParticipantImpl ->> PublisherImpl: 5.new
		DomainParticipantImpl ->> Publisher: 6.new
		DomainParticipantImpl ->> Publisher: 7.enable
		Publisher ->> PublisherImpl: 8.enable
		

1.用户程序调用DomainParticipant的create_publisher函数,这个函数调用的是DomainParticipantImpl的create_publisher函数

2.DomainParticipantImpl的create_publisher函数(3个参数)调用了自身的create_publisher函数(4个参数)

3.DomainParticipantImpl的create_publisher函数(4个参数) 主要干了4件事

a.创建PublisherImpl对象 见4

b.在PublisherImpl对象的基础上创建Publisher 见5

c.给PublisherImpl对象分配instance_handle(guid) 见6

d.调用Publisher对象的enable函数 见7

4.create_publisher_impl 创建PublisherImpl对象

5.创建PublisherImpl对象

6.在PublisherImpl的基础上创建publisher

7.调用Publisher的enable函数

8.调用PublisherImpl对象的enable函数

1.2源码

步骤1-2:

 Publisher* DomainParticipant::create_publisher(
         const PublisherQos& qos,
         PublisherListener* listener,
         const StatusMask& mask)
 {
     return impl_->create_publisher(qos, listener, mask);
 }
 ​
 ​
 Publisher* DomainParticipantImpl::create_publisher(
         const PublisherQos& qos,
         PublisherListener* listener,
         const StatusMask& mask)
 {
     return create_publisher(qos, nullptr, listener, mask);
 }
 ​

在DomainParticipantImpl中创建publisher

步骤3:

 Publisher* DomainParticipantImpl::create_publisher(
         const PublisherQos& qos,
         PublisherImpl** impl,
         PublisherListener* listener,
         const StatusMask& mask)
 {
     if (!PublisherImpl::check_qos(qos))
     {
         // The PublisherImpl::check_qos() function is not yet implemented and always returns ReturnCode_t::RETCODE_OK.
         // It will be implemented in future releases of Fast DDS.
         // EPROSIMA_LOG_ERROR(PARTICIPANT, "PublisherQos inconsistent or not supported");
         // return nullptr;
     }
 ​
     //TODO CONSTRUIR LA IMPLEMENTACION DENTRO DEL OBJETO DEL USUARIO.
     PublisherImpl* pubimpl = create_publisher_impl(qos, listener);
     Publisher* pub = new Publisher(pubimpl, mask);
     pubimpl->user_publisher_ = pub;
     pubimpl->rtps_participant_ = get_rtps_participant();
     bool enabled = get_rtps_participant() != nullptr;
 ​
     // Create InstanceHandle for the new publisher
     InstanceHandle_t pub_handle;
     create_instance_handle(pub_handle);
     pubimpl->handle_ = pub_handle;
 ​
     //SAVE THE PUBLISHER INTO MAPS
     std::lock_guard<std::mutex> lock(mtx_pubs_);
     publishers_by_handle_[pub_handle] = pub;
     publishers_[pub] = pubimpl;
 ​
     // Enable publisher if appropriate
     if (enabled && qos_.entity_factory().autoenable_created_entities)
     {
         ReturnCode_t ret_publisher_enable = pub->enable();
         assert(ReturnCode_t::RETCODE_OK == ret_publisher_enable);
         (void)ret_publisher_enable;
     }
 ​
     if (impl)
     {
         *impl = pubimpl;
     }
 ​
     return pub;
 }

干了这几件事

1.创建PublisherImpl对象

2.在PublisherImpl对象的基础上创建Publisher

3.给PublisherImpl对象分配instance_handle(guid)

4.调用Publisher对象的enable函数

步骤4:

 PublisherImpl* DomainParticipantImpl::create_publisher_impl(
         const PublisherQos& qos,
         PublisherListener* listener)
 {
     return new PublisherImpl(this, qos, listener);
 }
 ​

步骤5-6没啥关键信息

步骤7

 ReturnCode_t Publisher::enable()
 {
     if (enable_)
     {
         return ReturnCode_t::RETCODE_OK;
     }
 ​
     if (false == impl_->get_participant()->is_enabled())
     {
         return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
     }
 ​
     enable_ = true;
     ReturnCode_t ret_code = impl_->enable();
     enable_ = ReturnCode_t::RETCODE_OK == ret_code;
     return ret_code;
 }

步骤8:调用PublisherImpl::enable函数

 ReturnCode_t PublisherImpl::enable()
 {
     if (qos_.entity_factory().autoenable_created_entities)
     {
         std::lock_guard<std::mutex> lock(mtx_writers_);
         for (auto topic_writers : writers_)
         {
             for (DataWriterImpl* dw : topic_writers.second)
             {
                 dw->user_datawriter_->enable();
             }
         }
     }
 ​
     return ReturnCode_t::RETCODE_OK;
 }

调用PublisherImpl中的DataWriterImpl的DataWriter的enable函数

1.3类图

我们再参考看一下第一篇车载消息中间件FastDDS 源码解析(一)FastDDS 介绍和使用的类图

classDiagram
      
      DomainParticipantFactory *-- DomainParticipantImpl
      DomainParticipantImpl *-- PublisherImpl
      DomainParticipantImpl *-- SubscriberImpl
      DomainParticipantImpl *-- Topic
      DomainParticipantImpl *-- TypeSupport
      PublisherImpl *-- DataWriter
      SubscriberImpl *-- DataReader
      class DomainParticipantFactory {
      		+std::map<DomainId_t, std::vector<DomainParticipantImpl*>> participants_
      }
      class DomainParticipantImpl {
      		+PublisherQos default_pub_qos_
      		+std::map<Publisher*, PublisherImpl*> publishers_
      		+SubscriberQos default_sub_qos_
      		+std::map<Subscriber*, SubscriberImpl*> subscribers_
      		+TopicQos default_topic_qos_
      		+std::map<std::string, TopicProxyFactory*> topics_
      		+std::map<std::string, TypeSupport> types_
      }
      class PublisherImpl {
      		+std::map<std::string, std::vector<DataWriterImpl*>> writers_
      }
      class SubscriberImpl {
      		+std::map<std::string, std::vector<DataReaderImpl*>> readers_;
      }
      class Topic {
      
      }
      class TypeSupport {
      
      }
      class DataWriter {
      	
      }
      class DataReader {
      	
      }

如上面类图所示:

  1. DomainParticipantFactory管理所有的DomainParticipantImpl对象

  2. DomainParticipantImpl管理所有的Publisher,Topic,TypeSupport,Subscriber对象

  3. Publisher管理所有的DataWriter对象

    DataWriter 和 RTPSWriter 是一一对应的

  4. Subscriber管理所有的DataReader对象

    DataReader 和 RTPSReader 是一一对应的

2.创建Topic

 Topic* DomainParticipantImpl::create_topic(
         const std::string& topic_name,
         const std::string& type_name,
         const TopicQos& qos,
         TopicListener* listener,
         const StatusMask& mask)
 {
     //Look for the correct type registration
     TypeSupport type_support = find_type(type_name);
    ······
 ​
     std::lock_guard<std::mutex> lock(mtx_topics_);
 ​
     // Check there is no Topic with the same name
     if ((topics_.find(topic_name) != topics_.end()) ||
             (filtered_topics_.find(topic_name) != filtered_topics_.end()))
     {
         EPROSIMA_LOG_ERROR(PARTICIPANT, "Topic with name : " << topic_name << " already exists");
         return nullptr;
     }
 ​
     InstanceHandle_t topic_handle;
     create_instance_handle(topic_handle);
 ​
     TopicProxyFactory* factory = new TopicProxyFactory(this, topic_name, type_name, mask, type_support, qos, listener);
     TopicProxy* proxy = factory->create_topic();
     Topic* topic = proxy->get_topic();
     topic->set_instance_handle(topic_handle);
 ​
     //SAVE THE TOPIC INTO MAPS
     topics_by_handle_[topic_handle] = topic;
     topics_[topic_name] = factory;
 ​
     ······ 
 ​
     cond_topics_.notify_all();
 ​
     return topic;
 }

1.topic_handle赋值Guid,这个之后会分配给topic

2.创建TopicProxyFactory,里面初始化了一个TopicImpl对象

3.创建TopicProxy

4.获取topic,同时给topic赋值topic_handle

5.将topic 和 TopicProxyFactory存入DomainParticipantImpl,我们看一下1.3的类图

 TopicProxy* TopicProxyFactory::create_topic()
 {
     TopicProxy* ret_val = new TopicProxy(topic_name_, type_name_, status_mask_, &topic_impl_);
     proxies_.emplace_back(ret_val);
     return ret_val;
 }

创建TopicProxy,存入到列表中。

下面是关于topic的类图

classDiagram
      DomainParticipantImpl *-- TopicProxyFactory
      DomainParticipantImpl *-- TypeSupport
      TopicProxyFactory *-- TopicProxy
      TopicProxy *-- Topic
      
      class DomainParticipantImpl {
      		+TopicQos default_topic_qos_
      		+std::map<std::string, TopicProxyFactory*> topics_
      		+std::map<std::string, TypeSupport> types_
      }
      class TopicProxyFactory {
      		+std::list<std::unique_ptr<TopicProxy>> proxies_
      }
   
      class Topic {
      		+TopicProxy* impl_
      }
      class TopicProxy {
      		+Topic* user_topic_
      }
      class TypeSupport {
      
      }

我理解关于topic这块内容有点过度设计了,本身内容比较少,设计的类太多,设计得过于复杂了。

2.创建writer

2.1时序图

sequenceDiagram
		participant User
		participant PublisherImpl
		participant DataWriterImpl
		participant DataWriter
		participant RTPSDomainImpl
		participant RTPSParticipantImpl
		
		
		User ->> PublisherImpl:1.create_datawriter
		PublisherImpl ->> PublisherImpl:2.create_datawriter_impl
		PublisherImpl ->> DataWriterImpl:3.new
		PublisherImpl ->> PublisherImpl:4.create_datawriter
		PublisherImpl ->> DataWriter:5.new
		PublisherImpl ->> DataWriter:6.enable
		DataWriter ->> DataWriterImpl:7.enable
		DataWriterImpl ->> RTPSDomainImpl:8.create_rtps_writer
		RTPSDomainImpl ->> RTPSParticipantImpl:9.create_writer  
		DataWriterImpl ->> RTPSParticipantImpl:10.registerWriter
		

可以参考车载消息中间件FastDDS 源码解析(五)BuiltinProtocols(上)

车载消息中间件FastDDS 源码解析(六)BuiltinProtocols(中)EDP 创建PDP,EDP writer部分,PDP的writer一般是StatelessWriter,EDP的Writer一般是StatefulWriter。

1.Publisher的create_datawriter函数调用的是PublisherImpl的create_datawriter函数

PublisherImpl的create_datawriter函数最终干了3件事

a.获取TypeSupport

b.调用create_datawriter_impl函数来创建DataWriterImpl对象,传入参数TypeSupport对象 见步骤2

c.调用create_datawriter创建 DataWriter对象,传入参数DataWriterImpl对象 见步骤 4

2.PublisherImpl的create_datawriter_impl函数,调用了DataWriterImpl的初始化函数 创建了一个DataWriterImpl的对象

3.new 了一个DataWriterImpl对象

4.create_datawriter函数干了2件事:

a.new DataWriter,创建了一个DataWriter对象 见5

b.调用DataWriter对象的enable函数 见6

5.new 了一个DataWriter对象

6.DataWriter对象的enable函数 调用的是DataWriterImpl对象的enable函数

7.DataWriterImpl对象的enable函数 主要干了2件事

a.调用RTPSDomainImpl的create_rtps_writer函数 见 8

b.调用RTPSParticipantImpl的registerWriter函数 见 10

8.RTPSDomainImpl的create_rtps_writer函数主要是调用了RTPSParticipantImpl的create_writer函数

9.RTPSParticipantImpl的create_writer函数主要是创建了RTPSWriter

10.RTPSParticipantImpl的registerWriter函数主要是将writer的信息,存入PDP信息中,同时和reader进行匹配

具体内容可以参考本系列下一篇文章

2.2源码

步骤1:

 DataWriter* Publisher::create_datawriter(
         Topic* topic,
         const DataWriterQos& qos,
         DataWriterListener* listener,
         const StatusMask& mask)
 {
     return impl_->create_datawriter(topic, qos, listener, mask);
 }

调用publisherImpl的create_datawriter 来创建DataWriter

 DataWriter* PublisherImpl::create_datawriter(
         Topic* topic,
         const DataWriterQos& qos,
         DataWriterListener* listener,
         const StatusMask& mask)
 {
     EPROSIMA_LOG_INFO(PUBLISHER, "CREATING WRITER IN TOPIC: " << topic->get_name());
     //Look for the correct type registration
     TypeSupport type_support = participant_->find_type(topic->get_type_name());
 ​
     /// Preconditions
     // Check the type was registered.
     if (type_support.empty())
     {
         EPROSIMA_LOG_ERROR(PUBLISHER, "Type: " << topic->get_type_name() << " Not Registered");
         return nullptr;
     }
 ​
     if (!DataWriterImpl::check_qos_including_resource_limits(qos, type_support))
     {
         return nullptr;
     }
 ​
     DataWriterImpl* impl = create_datawriter_impl(type_support, topic, qos, listener);
     return create_datawriter(topic, impl, mask);
 }

主要干了3件事

1.获取TypeSupport

2.调用create_datawriter_impl函数来创建DataWriterImpl对象,传入参数TypeSupport对象 见步骤2

3.调用create_datawriter创建 DataWriter对象,传入参数DataWriterImpl对象 见步骤 4

步骤2:

 DataWriterImpl* PublisherImpl::create_datawriter_impl(
         const TypeSupport& type,
         Topic* topic,
         const DataWriterQos& qos,
         DataWriterListener* listener)
 {
     return new DataWriterImpl(this, type, topic, qos, listener);
 }

调用new DataWriterImpl,见步骤3

步骤3:

 DataWriterImpl::DataWriterImpl(
         PublisherImpl* p,
         TypeSupport type,
         Topic* topic,
         const DataWriterQos& qos,
         DataWriterListener* listen)
     : publisher_(p)
     , type_(type)
     , topic_(topic)
     , qos_(&qos == &DATAWRITER_QOS_DEFAULT ? publisher_->get_default_datawriter_qos() : qos)
     , listener_(listen)
     , history_(get_topic_attributes(qos_, *topic_, type_), type_->m_typeSize, qos_.endpoint().history_memory_policy,
             [this](
                 const InstanceHandle_t& handle) -> void
             {
                 if (nullptr != listener_)
                 {
                     listener_->on_unacknowledged_sample_removed(user_datawriter_, handle);
                 }
             })
 #pragma warning (disable : 4355 )
     , writer_listener_(this)
     , deadline_duration_us_(qos_.deadline().period.to_ns() * 1e-3)
     , lifespan_duration_us_(qos_.lifespan().duration.to_ns() * 1e-3)
 {
     EndpointAttributes endpoint_attributes;
     endpoint_attributes.endpointKind = WRITER;
     endpoint_attributes.topicKind = type_->m_isGetKeyDefined ? WITH_KEY : NO_KEY;
     endpoint_attributes.setEntityID(qos_.endpoint().entity_id);
     endpoint_attributes.setUserDefinedID(qos_.endpoint().user_defined_id);
     fastrtps::rtps::RTPSParticipantImpl::preprocess_endpoint_attributes<WRITER, 0x03, 0x02>(
         EntityId_t::unknown(), publisher_->get_participant_impl()->id_counter(), endpoint_attributes, guid_.entityId);
     guid_.guidPrefix = publisher_->get_participant_impl()->guid().guidPrefix;
 }

//为DataWriterImpl配置参数创建DataWriterImpl对象

history_ 是DataWriterHistory对象,在这儿初始化

步骤4:

 DataWriter* PublisherImpl::create_datawriter(
         Topic* topic,
         DataWriterImpl* impl,
         const StatusMask& mask)
 {
     topic->get_impl()->reference();
 ​
     DataWriter* writer = new DataWriter(impl, mask);
     impl->user_datawriter_ = writer;
 ​
     {
         std::lock_guard<std::mutex> lock(mtx_writers_);
         writers_[topic->get_name()].push_back(impl);
     }
 ​
     if (user_publisher_->is_enabled() && qos_.entity_factory().autoenable_created_entities)
     {
         if (ReturnCode_t::RETCODE_OK != writer->enable())
         {
             delete_datawriter(writer);
             return nullptr;
         }
     }
 ​
     return writer;
 }

以DataWriterImpl对象为参数创建DataWriter对象

调用DataWriter对象的enable函数

步骤6:

 ReturnCode_t DataWriter::enable()
 {
     if (enable_)
     {
         return ReturnCode_t::RETCODE_OK;
     }
 ​
     if (false == impl_->get_publisher()->is_enabled())
     {
         return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
     }
 ​
     ReturnCode_t ret_code = impl_->enable();
     enable_ = ReturnCode_t::RETCODE_OK == ret_code;
     return ret_code;
 }

调用DataWriterImpl::enable函数

步骤7:

 ReturnCode_t DataWriterImpl::enable()
 {
     assert(writer_ == nullptr);
 ​
     WriterAttributes w_att;
     w_att.throughputController = qos_.throughput_controller();
     w_att.endpoint.durabilityKind = qos_.durability().durabilityKind();
     w_att.endpoint.endpointKind = WRITER;
     w_att.endpoint.reliabilityKind = qos_.reliability().kind == RELIABLE_RELIABILITY_QOS ? RELIABLE : BEST_EFFORT;
     w_att.endpoint.topicKind = type_->m_isGetKeyDefined ? WITH_KEY : NO_KEY;
     w_att.endpoint.multicastLocatorList = qos_.endpoint().multicast_locator_list;
     w_att.endpoint.unicastLocatorList = qos_.endpoint().unicast_locator_list;
     w_att.endpoint.remoteLocatorList = qos_.endpoint().remote_locator_list;
     w_att.endpoint.external_unicast_locators = qos_.endpoint().external_unicast_locators;
     w_att.endpoint.ignore_non_matching_locators = qos_.endpoint().ignore_non_matching_locators;
     w_att.mode = qos_.publish_mode().kind == SYNCHRONOUS_PUBLISH_MODE ? SYNCHRONOUS_WRITER : ASYNCHRONOUS_WRITER;
     w_att.flow_controller_name = qos_.publish_mode().flow_controller_name;
     w_att.endpoint.properties = qos_.properties();
     w_att.endpoint.ownershipKind = qos_.ownership().kind;
     w_att.endpoint.setEntityID(qos_.endpoint().entity_id);
     w_att.endpoint.setUserDefinedID(qos_.endpoint().user_defined_id);
     w_att.times = qos_.reliable_writer_qos().times;
     w_att.liveliness_kind = qos_.liveliness().kind;
     w_att.liveliness_lease_duration = qos_.liveliness().lease_duration;
     w_att.liveliness_announcement_period = qos_.liveliness().announcement_period;
     w_att.matched_readers_allocation = qos_.writer_resource_limits().matched_subscriber_allocation;
     w_att.disable_heartbeat_piggyback = qos_.reliable_writer_qos().disable_heartbeat_piggyback;
 ​
     // TODO(Ricardo) Remove in future
     // Insert topic_name and partitions
     Property property;
     property.name("topic_name");
     property.value(topic_->get_name().c_str());
     w_att.endpoint.properties.properties().push_back(std::move(property));
 ​
     std::string* endpoint_partitions = PropertyPolicyHelper::find_property(qos_.properties(), "partitions");
 ​
     if (endpoint_partitions)
     {
         property.name("partitions");
         property.value(*endpoint_partitions);
         w_att.endpoint.properties.properties().push_back(std::move(property));
     }
     else if (publisher_->get_qos().partition().names().size() > 0)
     {
         property.name("partitions");
         std::string partitions;
         bool is_first_partition = true;
         for (auto partition : publisher_->get_qos().partition().names())
         {
             partitions += (is_first_partition ? "" : ";") + partition;
             is_first_partition = false;
         }
         property.value(std::move(partitions));
         w_att.endpoint.properties.properties().push_back(std::move(property));
     }
 ​
     if (qos_.reliable_writer_qos().disable_positive_acks.enabled &&
             qos_.reliable_writer_qos().disable_positive_acks.duration != c_TimeInfinite)
     {
         w_att.disable_positive_acks = true;
         w_att.keep_duration = qos_.reliable_writer_qos().disable_positive_acks.duration;
     }
 ​
     ReturnCode_t ret_code = check_datasharing_compatible(w_att, is_data_sharing_compatible_);
     if (ret_code != ReturnCode_t::RETCODE_OK)
     {
         return ret_code;
     }
 ​
     if (is_data_sharing_compatible_)
     {
         DataSharingQosPolicy datasharing(qos_.data_sharing());
         if (datasharing.domain_ids().empty())
         {
             datasharing.add_domain_id(utils::default_domain_id());
         }
         w_att.endpoint.set_data_sharing_configuration(datasharing);
     }
     else
     {
         DataSharingQosPolicy datasharing;
         datasharing.off();
         w_att.endpoint.set_data_sharing_configuration(datasharing);
     }
 ​
     bool filtering_enabled =
             qos_.liveliness().lease_duration.is_infinite() &&
             (0 < qos_.writer_resource_limits().reader_filters_allocation.maximum);
     if (filtering_enabled)
     {
         reader_filters_.reset(new ReaderFilterCollection(qos_.writer_resource_limits().reader_filters_allocation));
     }
 ​
     auto change_pool = get_change_pool();
     if (!change_pool)
     {
         EPROSIMA_LOG_ERROR(DATA_WRITER, "Problem creating change pool for associated Writer");
         return ReturnCode_t::RETCODE_ERROR;
     }
 ​
     auto pool = get_payload_pool();
     if (!pool)
     {
         EPROSIMA_LOG_ERROR(DATA_WRITER, "Problem creating payload pool for associated Writer");
         return ReturnCode_t::RETCODE_ERROR;
     }
 ​
     RTPSWriter* writer =  RTPSDomainImpl::create_rtps_writer(
         publisher_->rtps_participant(),
         guid_.entityId,
         w_att,
         pool,
         change_pool,
         //这儿使用DataWriterHistory 对象,也就是DataWriterImpl 和 RTPSWriter的WriterHistory是一个对象
         static_cast<WriterHistory*>(&history_),
         static_cast<WriterListener*>(&writer_listener_));
 ​
     if (writer == nullptr &&
             w_att.endpoint.data_sharing_configuration().kind() == DataSharingKind::AUTO)
     {
         EPROSIMA_LOG_INFO(DATA_WRITER, "Trying with a non-datasharing pool");
         release_payload_pool();
         is_data_sharing_compatible_ = false;
         DataSharingQosPolicy datasharing;
         datasharing.off();
         w_att.endpoint.set_data_sharing_configuration(datasharing);
 ​
         pool = get_payload_pool();
         if (!pool)
         {
             EPROSIMA_LOG_ERROR(DATA_WRITER, "Problem creating payload pool for associated Writer");
             return ReturnCode_t::RETCODE_ERROR;
         }
 ​
         writer = RTPSDomainImpl::create_rtps_writer(
             publisher_->rtps_participant(),
             guid_.entityId,
             w_att,
             pool,
             change_pool,
             static_cast<WriterHistory*>(&history_),
             static_cast<WriterListener*>(&writer_listener_));
     }
     if (writer == nullptr)
     {
         release_payload_pool();
         EPROSIMA_LOG_ERROR(DATA_WRITER, "Problem creating associated Writer");
         return ReturnCode_t::RETCODE_ERROR;
     }
 ​
     writer_ = writer;
     if (filtering_enabled)
     {
         writer_->reader_data_filter(this);
     }
 ​
     // In case it has been loaded from the persistence DB, rebuild instances on history
     history_.rebuild_instances();
 ​
     deadline_timer_ = new TimedEvent(publisher_->get_participant()->get_resource_event(),
                     [&]() -> bool
                     {
                         return deadline_missed();
                     },
                     qos_.deadline().period.to_ns() * 1e-6);
 ​
     lifespan_timer_ = new TimedEvent(publisher_->get_participant()->get_resource_event(),
                     [&]() -> bool
                     {
                         return lifespan_expired();
                     },
                     qos_.lifespan().duration.to_ns() * 1e-6);
 ​
     // In case it has been loaded from the persistence DB, expire old samples.
     if (qos_.lifespan().duration != c_TimeInfinite)
     {
         if (lifespan_expired())
         {
             lifespan_timer_->restart_timer();
         }
     }
 ​
     // REGISTER THE WRITER
     WriterQos wqos = qos_.get_writerqos(get_publisher()->get_qos(), topic_->get_qos());
     if (!is_data_sharing_compatible_)
     {
         wqos.data_sharing.off();
     }
     if (endpoint_partitions)
     {
         std::istringstream partition_string(*endpoint_partitions);
         std::string partition_name;
         wqos.m_partition.clear();
 ​
         while (std::getline(partition_string, partition_name, ';'))
         {
             wqos.m_partition.push_back(partition_name.c_str());
         }
     }
     publisher_->rtps_participant()->registerWriter(writer_, get_topic_attributes(qos_, *topic_, type_), wqos);
 ​
     return ReturnCode_t::RETCODE_OK;
 }

主要干了这几件事情

1.调用RTPSDomainImpl::create_rtps_writer创建了一个RTPSWriter,这是真正发送消息的对象

RTPSWriter的WriterHistory和DataWriterImpl的DataWriterHistory是共用的

2.创建了2个TimedEvent

deadline_timer_

fastdds 有个qos 叫deadlineqos ,这个qos的参数一般是个周期性的时间,规定了在周期性的时间内,发送端必须发送一个消息出来。

在接收端在这个周期性的时间内需要收到一个消息。

lifespan_timer_

fastdds有个qos 叫lifespanqos,这个qos规定了,一个消息的存活时间,超过时间,会在发送端将消息移除,这个默认设置,会把存活时间设置为无限。

3.调用RTPSParticipant::registerWriter,注册这个RTPSWriter

步骤8:

 RTPSWriter* RTPSDomainImpl::create_rtps_writer(
         RTPSParticipant* p,
         const EntityId_t& entity_id,
         WriterAttributes& watt,
         const std::shared_ptr<IPayloadPool>& payload_pool,
         const std::shared_ptr<IChangePool>& change_pool,
         WriterHistory* hist,
         WriterListener* listen)
 {
     RTPSParticipantImpl* impl = RTPSDomainImpl::find_local_participant(p->getGuid());
     if (impl)
     {
         RTPSWriter* ret_val = nullptr;
         if (impl->create_writer(&ret_val, watt, payload_pool, change_pool, hist, listen, entity_id))
         {
             return ret_val;
         }
     }
 ​
     return nullptr;
 }

调用RTPSParticipantImpl对象的create_writer,来创建RTPSWriter对象,创建的RTPSWriter

这个函数我们在之前介绍过,创建RTPSWriter,创建ReceiverResources,将ReceiverResources的MessageReceiver 与RTPSWriter关联,当MessageReceiver收到消息后,将会分配给相应的RTPSWriter或RTPSReader,让他们进行消息处理

2.3类图

classDiagram
      DomainParticipantImpl *-- PublisherImpl
      DomainParticipantImpl *-- Publisher
      Publisher *-- PublisherImpl
      PublisherImpl *-- DataWriterImpl
      DataWriterImpl *-- RTPSWriter
     
      class DomainParticipantImpl {
      		+PublisherQos default_pub_qos_
      		+std::map<Publisher*, PublisherImpl*> publishers_
      		+SubscriberQos default_sub_qos_
      		+std::map<Subscriber*, SubscriberImpl*> subscribers_	
      }
      class PublisherImpl {
      		+std::map<std::string, std::vector<DataWriterImpl*>> writers_
      		
      }
      class Publisher {
      	  +PublisherImpl* mp_impl
      		
      }
      
      class DataWriterImpl {
      		+RTPSWriter writer_
      }
  1. DomainParticipantImpl管理所有的Publisher对象

    Publisher 和 PublisherImpl 存储在一个map中( std::map<Publisher , PublisherImpl> publishers_ )

  2. Publisher 类似于 PublisherImpl的代理类,Publisher 和 PublisherImpl 是一一对应的。

  3. PublisherImpl管理着DataWriterImpl对象。

  4. DataWriter 和 RTPSWriter 是一一对应的。

    这块代码我理解有些部分是有点冗余的,Publisher 和 PublisherImpl,DataWriter和DataWriterImpl没必要分成2个类。