在读一读冰羚代码(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类至少要具备以下个功能:
- Sample类能够作为指针指向任何使用冰羚接口描述语言(IDL)定义的要发布的数据结构的对象
- Sample类能够提供和Publisher类一样的publish()接口功能
除此之外,为了使代码最大程度的优化,根据功能不同,Publisher中的Sample类拥有的接口和Subscriber中的Sample类拥有的接口应该有所区别。比如Publisher类中的Sample需要具备publish()接口,而Subcriber类中

最低0.47元/天 解锁文章
955

被折叠的 条评论
为什么被折叠?



