读一读冰羚代码(10)publisher数据发布之神奇的Sample类

读一读冰羚代码(9)publisher数据发布之寻找共享内存上的可用空间-优快云博客一文结尾处,从共享内存获取得到ChunkHeader对象,并最终被转换成Sample类对象:

template <typename T, typename H, typename BasePublisherType>
inline expected<Sample<T, H>, AllocationError> PublisherImpl<T, H, BasePublisherType>::loanSample() noexcept
{
    static constexpr uint32_t USER_HEADER_SIZE{std::is_same<H, mepoo::NoUserHeader>::value ? 0U : sizeof(H)};

    auto result = port().tryAllocateChunk(sizeof(T), alignof(T), USER_HEADER_SIZE, alignof(H));
    if (result.has_error())
    {
        return err(result.error());
    }
    else
    {
        return ok(convertChunkHeaderToSample(result.value()));
    }
}

先看下publisher的demo(iceoryx_examples/icehello/iox_publisher_helloworld.cpp):

while (!iox::hasTerminationRequested())
//! [wait for term]
{
    ++ct;

    // Retrieve a sample from shared memory
    //! [loan]
    auto loanResult = publisher.loan();
    //! [loan]
    //! [publish]
    if (loanResult.has_value())
    {
        auto& sample = loanResult.value();
        // Sample can be held until ready to publish
        sample->x = ct;      (1)
        sample->y = ct;
        sample->z = ct;
        sample.publish();    (2)
    }
}

(1)(2)两行有点出乎意料,因为,a. 要发布的数据结构其实有自己的定义(如下)。通常的做法,先初始化一个指向该数据结构的指针,然后利用该指针对数据成员赋值,代码中却利用Sample对象对要发布的数据结构RadarObject对象的数据成员赋值:

//! [radar object]
struct RadarObject
{
    double x = 0.0;
    double y = 0.0;
    double z = 0.0;
};
//! [radar object]

b. 既然Publisher对象已经构造完成,Published继承PublisherImpl,PublisherImpl定义有publish接口:

template <typename T, typename H = mepoo::NoUserHeader, typename BasePublisherType = BasePublisher<>>
class PublisherImpl : public BasePublisherType, private PublisherInterface<T, H>
{
  public:
    ///
    /// @brief publish Publishes the given sample and then releases its loan.
    /// @param sample The sample to publish.
    ///
    void publish(Sample<T, H>&& sample) noexcept override;
};

不能直接调用Publiser对象的publish接口来发布数据吗?

再来看下subscriber的demo(iceoryx_examples/icehello/iox_subscriber_helloworld.cpp):

int main()
{
    //! [initialize runtime]
    constexpr char APP_NAME[] = "iox-cpp-subscriber-helloworld";
    iox::runtime::PoshRuntime::initRuntime(APP_NAME);
    //! [initialize runtime]

    //! [initialize subscriber]
    iox::popo::Subscriber<RadarObject> subscriber({"Radar", "FrontLeft", "Object"});
    //! [initialize subscriber]

    // run until interrupted by Ctrl-C
    while (!iox::hasTerminationRequested())
    {
        //! [receive]
        auto takeResult = subscriber.take();    (1)
        if (takeResult.has_value())
        {
            std::cout << APP_NAME << " got value: " << takeResult.value()->x << std::endl;                                      (2)
        }
        //! [receive]
        else
        {
            //! [error]
            if (takeResult.error() == iox::popo::ChunkReceiveResult::NO_CHUNK_AVAILABLE)
            {
                std::cout << "No chunk available." << std::endl;
            }
            else
            {
                std::cout << "Error receiving chunk." << std::endl;
            }
            //! [error]
        }

        //! [wait]
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        //! [wait]
    }

    return (EXIT_SUCCESS);
}

(1)Subscriber对象从共享内存拿到的发布数据对象也被转换成了Sample对象

(2)利用Sample对象取出发布数据对象的数据成员

综合以上两个demo例程,Sample类至少要具备以下个功能:

  1. Sample类能够作为指针指向任何使用冰羚接口描述语言(IDL)定义的要发布的数据结构的对象
  2. Sample类能够提供和Publisher类一样的publish()接口功能

除此之外,为了使代码最大程度的优化,根据功能不同,Publisher中的Sample类拥有的接口和Subscriber中的Sample类拥有的接口应该有所区别。比如Publisher类中的Sample需要具备publish()接口,而Subcriber类中

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值