第一篇 一个例子
车载消息中间件FastDDS 源码解析(一)FastDDS 介绍和使用
第二篇fastdds的组成
车载消息中间件FastDDS 源码解析(二)RtpsParticipant的创建(上)
车载消息中间件FastDDS 源码解析(三)RtpsParticipant的创建(中)
车载消息中间件FastDDS 源码解析(四)RtpsParticipant的创建(下)
车载消息中间件FastDDS 源码解析(五)BuiltinProtocols(上)
车载消息中间件FastDDS 源码解析(六)BuiltinProtocols(中)EDP
车载消息中间件FastDDS 源码解析(七)BuiltinProtocols(下)WLP&TypeLookupManager
车载消息中间件FastDDS 源码解析(八)TimedEvent
第三篇组网建立连接
pdp建连
车载消息中间件FastDDS 源码解析(十)发送第一条PDP消息(上)
FastDDS 源码解析(十二)发送第一条PDP消息(下)---异步发送
FastDDS 源码解析(十三)发送第一条PDP消息---跨进程发送
FastDDS 源码解析(十六)处理PDP消息——PDP匹配
EDP建连
FastDDS 源码解析(十七)处理PDP消息——EDP匹配
FastDDS 源码解析(十八)EDP阶段发送心跳heartbeat
FastDDS 源码解析(十九)EDP阶段处理heartbeat消息,发送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 {
}
如上面类图所示:
-
DomainParticipantFactory管理所有的DomainParticipantImpl对象
-
DomainParticipantImpl管理所有的Publisher,Topic,TypeSupport,Subscriber对象
-
Publisher管理所有的DataWriter对象
DataWriter 和 RTPSWriter 是一一对应的
-
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_
}
-
DomainParticipantImpl管理所有的Publisher对象
Publisher 和 PublisherImpl 存储在一个map中( std::map<Publisher , PublisherImpl> publishers_ )
-
Publisher 类似于 PublisherImpl的代理类,Publisher 和 PublisherImpl 是一一对应的。
-
PublisherImpl管理着DataWriterImpl对象。
-
DataWriter 和 RTPSWriter 是一一对应的。
这块代码我理解有些部分是有点冗余的,Publisher 和 PublisherImpl,DataWriter和DataWriterImpl没必要分成2个类。