Init
template <typename MessageT>
bool Reader<MessageT>::Init() {
if (init_.exchange(true)) {
return true;
}
std::function<void(const std::shared_ptr<MessageT>&)> func;
if (reader_func_ != nullptr) {
func = [this](const std::shared_ptr<MessageT>& msg) {
this->Enqueue(msg);
this->reader_func_(msg);
};
} else {
func = [this](const std::shared_ptr<MessageT>& msg) { this->Enqueue(msg); };
}
auto sched = scheduler::Instance();
croutine_name_ = role_attr_.node_name() + "_" + role_attr_.channel_name();
auto dv = std::make_shared<data::DataVisitor<MessageT>>(
role_attr_.channel_id(), pending_queue_size_);
// Using factory to wrap templates.
croutine::RoutineFactory factory =
croutine::CreateRoutineFactory<MessageT>(std::move(func), dv);
if (!sched->CreateTask(factory, croutine_name_)) {
AERROR << "Create Task Failed!";
init_.store(false);
return false;
}
receiver_ = ReceiverManager<MessageT>::Instance()->GetReceiver(role_attr_);
this->role_attr_.set_id(receiver_->id().HashValue());
channel_manager_ =
service_discovery::TopologyManager::Instance()->channel_manager();
JoinTheTopology();
return true;
}
- 原子交换初始化标志:
-
- 首先,它尝试通过init_.exchange(true)设置初始化标志为true。如果这个操作成功(即之前未被初始化),则直接返回true,表示已经初始化过了或者同时有其他线程正在初始化。
- 定义消息处理函数:
-
- 根据成员变量reader_func_是否为空,定义了两种消息处理逻辑。如果不为空,意味着用户自定义了一个消息处理回调,因此创建一个lambda函数,该函数先将消息入队到内部队列,然后调用用户提供的回调处理消息。如果为空,则只执行入队操作。
- 创建数据访问器和协程工厂:
-
- 实例化一个data::DataVisitor对象,它负责管理指定大小的消息缓冲队列。
- 使用croutine::CreateRoutineFactory创建一个协程工厂,传入前面定义的lambda作为消息处理函数和刚创建的数据访问器。这个工厂是为了能够创建处理特定类型MessageT消息的协程。
- 在调度器中创建任务:
-
- 获取全局的调度器实例,并尝试使用上面创建的协程工厂创建一个任务,任务名称由节点名和通道名组合而成。如果创建失败,则记录错误日志,回滚初始化标志,并返回false。
- 注册接收器和设置角色属性:
-
- 从一个管理接收器的单例类中获取与当前角色属性(role_attr_)匹配的接收器实例。
- 设置角色的ID为获取到的接收器ID的哈希值。
- 加入拓扑结构:
-
- 获取服务发现模块中的通道管理器实例,这通常涉及到系统中各组件如何相互通信的管理。
- 调用JoinTheTopology()方法(未在代码片段中定义),可能涉及向系统拓扑中注册当前读取器,以便其他组件可以发现并与其通信。
JoinTheTopology
oid Reader<MessageT>::JoinTheTopology() {
// add listener
change_conn_ = channel_manager_->AddChangeListener(std::bind(
&Reader<MessageT>::OnChannelChange, this, std::placeholders::_1));
// get peer writers
const std::string& channel_name = this->role_attr_.channel_name();
std::vector<proto::RoleAttributes> writers;
channel_manager_->GetWritersOfChannel(channel_name, &writers);
for (auto& writer : writers) {
receiver_->Enable(writer);
}
channel_manager_->Join(this->role_attr_, proto::RoleType::ROLE_READER,
message::HasSerializer<MessageT>::value);
}
从上面可以看出,JoinTheTopology函数中,同样的注册了参与者发现的回调函数,然后获取channelname,然后根据channelname获取名字,
template <typename MessageT>
void Reader<MessageT>::OnChannelChange(const proto::ChangeMsg& change_msg) {
if (change_msg.role_type() != proto::RoleType::ROLE_WRITER) {
return;
}
auto& writer_attr = change_msg.role_attr();
if (writer_attr.channel_name() != this->role_attr_.channel_name()) {
return;
}
auto operate_type = change_msg.operate_type();
if (operate_type == proto::OperateType::OPT_JOIN) {
receiver_->Enable(writer_attr);
} else {
receiver_->Disable(writer_attr);
}
}