类MessageLite
所有message的接口类,从名字看是lite的message,普通message也是它的子类。
MessageLite适合“轻量级”的message(仅仅提供 encoding+序列化 功能,没有使用使用reflection和descriptors)。在确定可以使用“轻量级”的message的场景下,可以在.proto文件中如下增加配置(option optimize_for = LITE_RUNTIME;),来让protocol compiler产出MessageLite类型的类,这样可以节省runtime资源。
类Message
接口类,在类MessageLite的基础上增加了descriptors和reflection。
类MessageFactory
接口类,来创建Message对象,底层是封装了GeneratedMessageFactory类。
类GeneratedMessageFactory
MessageFactory的子类,singleton模式。
singleton模式是通过全局变量GeneratedMessageFactory* generated_message_factory_结合GOOGLE_PROTOBUF_DECLARE_ONCE(本质是pthread_once)来实现。
内部核心数据结构:
hash_map<const char*, RegistrationFunc*>: 成员变量file_map_,从文件名到注册函数的映射关系,这个关系是在static初始化阶段完成,所以不需要锁;hash_map<const Descriptor*, const Message*>:成员变量type_map_,Descriptor*到对应Message*(这里其实是Message的prototype,调用它的New()接口,才创建具体的Message对象)的映射关系,这个关系会涉及多线程处理,使用读写锁保护;
对外关键接口:
const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type)
功能:
从descriptor找到对应message的prototype
处理流程:
- 上读锁,从
hash_map<const Descriptor*, const Message*>找,有则返回、无则继续; - 校验descriptor对应proto文件是否由全局的DescriptorPool管理;
- 用descriptor对应文件名从
hash_map<const char*, RegistrationFunc*>找注册函数registration_func,无则返回、有则继续; - 上写锁,判断是否有其它线程已经抢占(preempt)写入
hash_map<const Descriptor*, const Message*>。如果没有,调用registration_func完成注册。并且从hash_map<const Descriptor*, const Message*>找到对应Message的prototype
void RegisterFile(const char* file, RegistrationFunc* registration_func)
功能:
注册file_name和对应的注册函数到hash_map<const char*, RegistrationFunc*>
void RegisterType(const Descriptor* descriptor, const Message* prototype)
功能:
注册descriptor和message的关系到hash_map<const Descriptor*, const Message*>
注册关系的生成:
在每个.pb.cc都会调用,例如protobuf/compiler/plugin.pb.cc 中:
void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
…… // 省略
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
…… // 省略
}
注册函数定义也在protobuf/compiler/plugin.pb.cc 中:
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
}
针对plugin.proto中的每一个Message,都会有对应的descriptor和default message对象:
CodeGeneratorRequest_descriptor_和CodeGeneratorRequest::default_instance()
void MessageFactory::InternalRegisterGeneratedMessage(
const Descriptor* descriptor, const Message* prototype) {
GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
}
最终是调用了 GeneratedMessageFactory::RegisterType():
void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
const Message* prototype) {
… // 省略
if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
… // 省略
}
类DynamicMessageFactory
MessageFactory的子类,用于处理非compile-time的message。
相关类的关系图

本文详细介绍了 Protobuf 的消息类,包括MessageLite、Message和MessageFactory等。MessageLite是轻量级消息接口,提供编码和序列化功能;Message在MessageLite基础上增加了descriptors和reflection;MessageFactory是创建Message对象的接口,GeneratedMessageFactory是其实现,采用singleton模式。此外,文章还讨论了内部核心数据结构、关键接口及其功能,以及动态消息工厂DynamicMessageFactory。
1768

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



