Protobuf-Message相关类
类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。