欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Protobuf-Message相关类

程序员文章站 2022-05-13 22:41:37
...

类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)来实现。

内部核心数据结构:

  1. hash_map<const char*, RegistrationFunc*>: 成员变量file_map_,从文件名到注册函数的映射关系,这个关系是在static初始化阶段完成,所以不需要锁;
  2. hash_map<const Descriptor*, const Message*>:成员变量type_map_Descriptor*到对应 Message*(这里其实是Message的prototype,调用它的New()接口,才创建具体的Message对象)的映射关系,这个关系会涉及多线程处理,使用读写锁保护;

对外关键接口:

const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type)

功能:

从descriptor找到对应message的prototype

处理流程:

  1. 上读锁,从hash_map<const Descriptor*, const Message*>找,有则返回、无则继续;
  2. 校验descriptor对应proto文件是否由全局的DescriptorPool管理;
  3. 用descriptor对应文件名从hash_map<const char*, RegistrationFunc*>找注册函数registration_func,无则返回、有则继续;
  4. 上写锁,判断是否有其它线程已经抢占(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-Message相关类

相关标签: protobuf