namespace movex {
namespace cyber {
namespace transport {
class Segment;
using SegmentPtr = std::shared_ptr<Segment>;
struct WritableBlock {
uint32_t index = 0;
Block* block = nullptr;
uint8_t* buf = nullptr;
};
using ReadableBlock = WritableBlock;
class Segment {
public:
explicit Segment(uint64_t channel_id);
virtual ~Segment() {}
bool AcquireBlockToWrite(std::size_t msg_size, WritableBlock* writable_block);
void ReleaseWrittenBlock(const WritableBlock& writable_block);
bool AcquireBlockToRead(ReadableBlock* readable_block);
void ReleaseReadBlock(const ReadableBlock& readable_block);
void CheckSegmentBlock();
protected:
virtual bool Destroy();
virtual void Reset() = 0;
virtual bool Remove() = 0;
virtual bool OpenOnly() = 0;
virtual bool OpenOrCreate() = 0;
bool init_;
ShmConf conf_;
uint64_t channel_id_;
State* state_;
Block* blocks_;
void* managed_shm_;
std::mutex block_buf_lock_;
std::unordered_map<uint32_t, uint8_t*> block_buf_addrs_;
private:
bool Remap();
bool Recreate(const uint64_t& msg_size);
uint32_t GetNextWritableBlockIndex();
};
} // namespace transport
} // namespace cyber
} // namespace movex
namespace movex {
namespace cyber {
namespace transport {
namespace {
constexpr double kBlockLockTime = 10.0;
}
Segment::Segment(uint64_t channel_id)
: init_(false),
conf_(),
channel_id_(channel_id),
state_(nullptr),
blocks_(nullptr),
managed_shm_(nullptr),
block_buf_lock_(),
block_buf_addrs_() {}
bool Segment::AcquireBlockToWrite(std::size_t msg_size,
WritableBlock* writable_block) {
RETURN_VAL_IF_NULL(writable_block, false);
/*创建共享内存以及块的概念 具体见下面分析*/
if (!init_ && !OpenOrCreate()) {
AERROR << "create shm failed, can't write now.";
return false;
}
/* 判断是否需要重新映射*/
bool result = true;
if (state_->need_remap()) {
result = Remap();
}
/*消息过大的话,立即销毁重新开始OpenOrCreate(),大小重新分配*/
if (msg_size > conf_.ceiling_msg_size()) {
AINFO << "msg_size: " << msg_size
<< " larger than current shm_buffer_size: "
<< conf_.ceiling_msg_size() << " , need recreate.";
result = Recreate(msg_size);
}
if (!result) {
AERROR << "segment update failed.";
return false;
}
uint32_t index = GetNextWritableBlockIndex();
if (UINT32_MAX == index) {
return false;
}
writable_block->index = index;
writable_block->block = &blocks_[index];
writable_block->buf = block_buf_addrs_[index];
return true;
}
void Segment::ReleaseWrittenBlock(const WritableBlock& writable_block) {
auto index = writable_block.index;
if (index >= conf_.block_num()) {
return;
}
blocks_[index].ReleaseWriteLock();
}
bool Segment::AcquireBlockToRead(ReadableBlock* readable_block) {
RETURN_VAL_IF_NULL(readable_block, false);
if (!init_ && !OpenOnly()) {
AERROR << "failed to open shared mem