apollo源码分析之节点创建与运行流程

本文以apollo官方例子CommonComponentSample进行分析,CommonComponentSample声明如下:

File: /home/lgy/opensource/apollo/cyber/examples/common_component_example/common_component_example.h
25: class CommonComponentSample : public Component<Driver, Driver> {
26:  public:
27:   bool Init() override;
28:   bool Proc(const std::shared_ptr<Driver>& msg0,
29:             const std::shared_ptr<Driver>& msg1) override;
30: };
31: CYBER_REGISTER_COMPONENT(CommonComponentSample)

看到这段例子,有几个疑问:
1.为什么需要定义Init以及Proc函数?
2. CYBER_REGISTER_COMPONENT(CommonComponentSample)背后做了什么?
3.这个节点时如何运行的?Init以及Proc是如何被调用的?

1.为什么需要定义Init以及Proc函数?

我们看CommonComponentSample的类继承关系

File: /home/lgy/opensource/apollo/cyber/component/component.h
56: template <typename M0 = NullType, typename M1 = NullType,
57:           typename M2 = NullType, typename M3 = NullType>
File: /home/lgy/opensource/apollo/cyber/component/component.h
58: class Component : public ComponentBase {
		...
108:  private:
109:   virtual bool Proc(const std::shared_ptr<M0>& msg) = 0;
110: };

File: /home/lgy/opensource/apollo/cyber/component/component_base.h
40: 
41: class ComponentBase : public std::enable_shared_from_this<ComponentBase> {
		...
66: 
67:  protected:
68:   virtual bool Init() = 0;
		...
116: };

这些纯虚函数需要我们定义的。

2. CYBER_REGISTER_COMPONENT(CommonComponentSample)背后做了什么?

我们将CYBER_REGISTER_COMPONENT宏展开

File: /home/lgy/opensource/apollo/cyber/component/component.h
551: #define CYBER_REGISTER_COMPONENT(name) \
552:   CLASS_LOADER_REGISTER_CLASS(name, apollo::cyber::ComponentBase)

File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader_register_macro.h
36: // register class macro
37: #define CLASS_LOADER_REGISTER_CLASS(Derived, Base) \
38:   CLASS_LOADER_REGISTER_CLASS_INTERNAL_1(Derived, Base, __COUNTER__)


File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader_register_macro.h
33: #define CLASS_LOADER_REGISTER_CLASS_INTERNAL_1(Derived, Base, UniqueID) \
34:   CLASS_LOADER_REGISTER_CLASS_INTERNAL(Derived, Base, UniqueID)


File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader_register_macro.h
22: #define CLASS_LOADER_REGISTER_CLASS_INTERNAL(Derived, Base, UniqueID)     \
23:   namespace {                                                             \
24:   struct ProxyType##UniqueID {                                            \
25:     ProxyType##UniqueID() {                                               \
26:       apollo::cyber::class_loader::utility::RegisterClass<Derived, Base>( \
27:           #Derived, #Base);                                               \
28:     }                                                                     \
29:   };                                                                      \
30:   static ProxyType##UniqueID g_register_class_##UniqueID;                 \
31:   }

宏定义规则:参考https://segmentfault.com/a/1190000038216844

如果在宏定义的替换文本中,参数名以 # 作为前缀则结果将被扩展为由实际参数替换该参数的带引号的字符串。例如,可以将它与字符串连接运算结合起来编写一个调试打印宏:

#define dprint(expr) printf(#expr " = %gn", expr)
使用语句

dprint(x/y);
调用该宏时,该宏将被扩展为:

printf("x/y" " = %gn", x/y);
其中的字符串被拼接起来了,这样,该宏调用的效果等价于

printf("x/y = %gn", x/y);
预处理器运算符 ## 为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与 ## 相邻,则该参数将被实际参数替代,## 与前后的空白符将被删除,并对替换后的结果重新扫描。例如,下面定义的宏 paste 用于连接两个参数:

#define paste(front, back) front ## back
因此,宏调用 paste(name, 1) 的结果将建立记号 name1。

经过分析替换过程中:Base=apollo::cyber::ComponentBase Derived=CommonComponentSample COUNTER:比如1234,则CYBER_REGISTER_COMPONENT(CommonComponentSample) 展开后为:

namespace {                                                             
  struct ProxyType1234 {                                           
    ProxyType1234() {                                               
      apollo::cyber::class_loader::utility::RegisterClass<CommonComponentSample, apollo::cyber::ComponentBase>("CommonComponentSample", "apollo::cyber::ComponentBase");   
  	}                                                                     
  };                                                                      
  static ProxyType1234 g_register_class_1234;                 
}

代码定义了一个g_register_class_1234静态变量,从而调用器构造函数,进而调用 apollo::cyber::class_loader::utility::RegisterClass,我们接着分析。

File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.h
76: template <typename Derived, typename Base>
77: void RegisterClass(const std::string& class_name,
78:                    const std::string& base_class_name) {
79:   AINFO << "registerclass:" << class_name << "," << base_class_name << ","
80:         << GetCurLoadingLibraryName();
81: 
82:   utility::AbstractClassFactory<Base>* new_class_factory_obj =
83:       new utility::ClassFactory<Derived, Base>(class_name, base_class_name);
84:   new_class_factory_obj->AddOwnedClassLoader(GetCurActiveClassLoader());
85:   new_class_factory_obj->SetRelativeLibraryPath(GetCurLoadingLibraryName());
86: 
87:   GetClassFactoryMapMapMutex().lock();
88:   ClassClassFactoryMap& factory_map =
89:       GetClassFactoryMapByBaseClass(typeid(Base).name());
90:   factory_map[class_name] = new_class_factory_obj;
91:   GetClassFactoryMapMapMutex().unlock();
92: }


File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.cc
34: BaseToClassFactoryMapMap& GetClassFactoryMapMap() {
35:   static BaseToClassFactoryMapMap instance;
36:   return instance;
37: }

File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.h
49: using BaseToClassFactoryMapMap = std::map<std::string, ClassClassFactoryMap>;
50: 

File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.h
47: using ClassClassFactoryMap =
48:     std::map<std::string, utility::AbstractClassFactoryBase*>;

File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.cc
44: ClassClassFactoryMap& GetClassFactoryMapByBaseClass(
45:     const std::string& typeid_base_class_name) {
46:   BaseToClassFactoryMapMap& factoryMapMap = GetClassFactoryMapMap();
47:   std::string base_class_name = typeid_base_class_name;
48:   if (factoryMapMap.find(base_class_name) == factoryMapMap.end()) {
49:     factoryMapMap[base_class_name] = ClassClassFactoryMap();
50:   }
51: 
52:   return factoryMapMap[base_class_name];
53: }

最终创建了new_class_factory_obj放到factory_map[class_name]中。factory_map[class_name]如何使用?节点运行时我们再接着分析。

3.这个节点时如何运行的?Init以及Proc是如何被调用的?

我们看节点启动命令

File: /home/lgy/opensource/apollo/cyber/examples/common_component_example/README.md
27: ### Start the sample component
30: cyber_launch start cyber/examples/common_component_example/common.launch
33: Or
36: mainboard -d cyber/examples/common_component_example/common.dag

mainboard从哪里来?

File: /home/lgy/opensource/apollo/cyber/mainboard/BUILD
7: cc_binary(
8:     name = "mainboard",
9:     srcs = [
10:         "mainboard.cc",
11:         "module_argument.cc",
12:         "module_argument.h",
13:         "module_controller.cc",
14:         "module_controller.h",
15:     ],
16:     linkopts = ["-pthread"],
17:     linkstatic = False,
18:     deps = [
19:         "//cyber:cyber_core",
20:         "//cyber/proto:dag_conf_cc_proto",
21:     ],
22: )
23: 

从BUILD文件可以看出mainboard由mainboard.cc等编译而来。mainboard.c源码如下:

File: /home/lgy/opensource/apollo/cyber/mainboard/mainboard.cc
27: int main(int argc, char** argv) {
28:   // parse the argument
29:   ModuleArgument module_args;
30:   module_args.ParseArgument(argc, argv);
31: 
32:   // initialize cyber
33:   apollo::cyber::Init(argv[0]);
34: 
35:   // start module
36:   ModuleController controller(module_args);
37:   if (!controller.Init()) {
38:     controller.Clear();
39:     AERROR << "module start error.";
40:     return -1;
41:   }
42: 
43:   apollo::cyber::WaitForShutdown();
44:   controller.Clear();
45:   AINFO << "exit mainboard.";
46: 
47:   return 0;
48: }

我们看如下几个步骤:
1.module_args.ParseArgument(argc, argv); //猜测就是参数解析
2.ModuleController controller(module_args); //使用解析到的参数module_args创建了controller变量
3.controller.Init() //堆controller执行Init初始化函数。

3.1.参数解析module_args.ParseArgument(argc, argv);

File: /home/lgy/opensource/apollo/cyber/mainboard/module_argument.cc
43: void ModuleArgument::ParseArgument(const int argc, char* const argv[]) {
44:   binary_name_ = std::string(basename(argv[0]));
45:   GetOptions(argc, argv);
46: 
47:   if (process_group_.empty()) {
48:     process_group_ = DEFAULT_process_group_;
49:   }
50: 
51:   if (sched_name_.empty()) {
52:     sched_name_ = DEFAULT_sched_name_;
53:   }
54: 
55:   GlobalData::Instance()->SetProcessGroup(process_group_);
56:   GlobalData::Instance()->SetSchedName(sched_name_);
57:   AINFO << "binary_name_ is " << binary_name_ << ", process_group_ is "
58:         << process_group_ << ", has " << dag_conf_list_.size() << " dag conf";
59:   for (std::string& dag : dag_conf_list_) {
60:     AINFO << "dag_conf: " << dag;
61:   }
62: }
63: 
64: void ModuleArgument::GetOptions(const int argc, char* const argv[]) {
65:   opterr = 0;  // extern int opterr
66:   int long_index = 0;
67:   const std::string short_opts = "hd:p:s:";
68:   static const struct option long_opts[] = {
69:       {"help", no_argument, nullptr, 'h'},
70:       {"dag_conf", required_argument, nullptr, 'd'},
71:       {"process_name", required_argument, nullptr, 'p'},
72:       {"sched_name", required_argument, nullptr, 's'},
73:       {NULL, no_argument, nullptr, 0}};
74: 
75:   // log command for info
76:   std::string cmd("");
77:   for (int i = 0; i < argc; ++i) {
78:     cmd += argv[i];
79:     cmd += " ";
80:   }
81:   AINFO << "command: " << cmd;
82: 
83:   if (1 == argc) {
84:     DisplayUsage();
85:     exit(0);
86:   }
87: 
88:   do {
89:     int opt =
90:         getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index);
91:     if (opt == -1) {
92:       break;
93:     }
94:     switch (opt) {
95:       case 'd':
96:         dag_conf_list_.emplace_back(std::string(optarg));
97:         for (int i = optind; i < argc; i++) {
98:           if (*argv[i] != '-') {
99:             dag_conf_list_.emplace_back(std::string(argv[i]));
100:           } else {
101:             break;
102:           }
103:         }
104:         break;
105:       case 'p':
106:         process_group_ = std::string(optarg);
107:         break;
108:       case 's':
109:         sched_name_ = std::string(optarg);
110:         break;
111:       case 'h':
112:         DisplayUsage();
113:         exit(0);
114:       default:
115:         break;
116:     }
117:   } while (true);
118: 
119:   if (optind < argc) {
120:     AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\"";
121:     DisplayUsage();
122:     exit(1);
123:   }
124: 
125:   if (dag_conf_list_.empty()) {
126:     AINFO << "-d parameter must be specified";
127:     DisplayUsage();
128:     exit(1);
129:   }
130: }

我们的调用命令是mainboard -d cyber/examples/common_component_example/common.dag,经过参数解析后cyber/examples/common_component_example/common.dag放进了dag_conf_list_链表中。

3.2.ModuleController controller变量ModuleController做了什么事情?

File: /home/lgy/opensource/apollo/cyber/mainboard/module_controller.h
56: inline ModuleController::ModuleController(const ModuleArgument& args)
57:     : args_(args) {}
58: 
59: inline bool ModuleController::Init() { return LoadAll(); }

File: /home/lgy/opensource/apollo/cyber/mainboard/module_controller.cc
37: bool ModuleController::LoadAll() {
38:   const std::string work_root = common::WorkRoot();
39:   const std::string current_path = common::GetCurrentPath();
40:   const std::string dag_root_path = common::GetAbsolutePath(work_root, "dag");
	  //将dag_conf_list_链表中的dag文件依次放入paths中
41:   std::vector<std::string> paths;
42:   for (auto& dag_conf : args_.GetDAGConfList()) {
43:     std::string module_path = "";
44:     if (dag_conf == common::GetFileName(dag_conf)) {
45:       // case dag conf argument var is a filename
46:       module_path = common::GetAbsolutePath(dag_root_path, dag_conf);
47:     } else if (dag_conf[0] == '/') {
48:       // case dag conf argument var is an absolute path
49:       module_path = dag_conf;
50:     } else {
51:       // case dag conf argument var is a relative path
52:       module_path = common::GetAbsolutePath(current_path, dag_conf);
53:       if (!common::PathExists(module_path)) {
54:         module_path = common::GetAbsolutePath(work_root, dag_conf);
55:       }
56:     }
57:     total_component_nums += GetComponentNum(module_path);
58:     paths.emplace_back(std::move(module_path));
59:   }
60:   if (has_timer_component) {
61:     total_component_nums += scheduler::Instance()->TaskPoolSize();
62:   }
63:   common::GlobalData::Instance()->SetComponentNums(total_component_nums);
	  //遍历paths执行LoadModule动作
64:   for (auto module_path : paths) {
65:     AINFO << "Start initialize dag: " << module_path;
66:     if (!LoadModule(module_path)) {
67:       AERROR << "Failed to load module: " << module_path;
68:       return false;
69:     }
70:   }
71:   return true;
72: }

File: /home/lgy/opensource/apollo/cyber/mainboard/module_argument.h
65: inline const std::list<std::string>& ModuleArgument::GetDAGConfList() const {
66:   return dag_conf_list_;
67: }


File: /home/lgy/opensource/apollo/cyber/mainboard/module_controller.cc
74: bool ModuleController::LoadModule(const DagConfig& dag_config) {
75:   const std::string work_root = common::WorkRoot();
76: 
77:   for (auto module_config : dag_config.module_config()) {
		//获取load路径
78:     std::string load_path;
79:     if (module_config.module_library().front() == '/') {
80:       load_path = module_config.module_library();
81:     } else {
82:       load_path =
83:           common::GetAbsolutePath(work_root, module_config.module_library());
84:     }
85: 
86:     if (!common::PathExists(load_path)) {
87:       AERROR << "Path does not exist: " << load_path;
88:       return false;
89:     }
90: 	
		//调用class_loader_manager_.LoadLibrary加载库
91:     class_loader_manager_.LoadLibrary(load_path);
92: 
93:     for (auto& component : module_config.components()) {
94:       const std::string& class_name = component.class_name();
		  //创建CreateClassObj 初始化Initialize
95:       std::shared_ptr<ComponentBase> base =
96:           class_loader_manager_.CreateClassObj<ComponentBase>(class_name);
97:       if (base == nullptr || !base->Initialize(component.config())) {
98:         return false;
99:       }
100:       component_list_.emplace_back(std::move(base));
101:     }
102: 
103:     for (auto& component : module_config.timer_components()) {
104:       const std::string& class_name = component.class_name();
105:       std::shared_ptr<ComponentBase> base =
106:           class_loader_manager_.CreateClassObj<ComponentBase>(class_name);
107:       if (base == nullptr || !base->Initialize(component.config())) {
108:         return false;
109:       }
110:       component_list_.emplace_back(std::move(base));
111:     }
112:   }
113:   return true;
114: }
115: 
116: bool ModuleController::LoadModule(const std::string& path) {
117:   DagConfig dag_config;
118:   if (!common::GetProtoFromFile(path, &dag_config)) {
119:     AERROR << "Get proto failed, file: " << path;
120:     return false;
121:   }
122:   return LoadModule(dag_config);
123: }

这部分的函数调用关系如下:

ModuleController::Init()
	bool ModuleController::LoadAll()
		bool ModuleController::LoadModule(const DagConfig& dag_config) 
			class_loader_manager_.LoadLibrary(load_path);//加载库
			std::shared_ptr<ComponentBase> base = class_loader_manager_.CreateClassObj<ComponentBase>(class_name);//创建对象
	       	base->Initialize(component.config());//初始化

从调用关系看最终到了class_loader_manager_加载库、创建对象、初始化对象,接下来我们分析。

3.3 class_loader_manager_如何加载库、创建对象、初始化对象

3.3.1. class_loader_manager_如何加载库

从class_loader_manager_.LoadLibrary(load_path);分析

File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader_manager.cc
39: std::vector<std::string> ClassLoaderManager::GetAllValidLibPath() {
40:   std::vector<std::string> libpath;
41:   for (auto& lib_class_loader : libpath_loader_map_) {
42:     if (lib_class_loader.second != nullptr) {
43:       libpath.emplace_back(lib_class_loader.first);
44:     }
45:   }
46:   return libpath;
47: }
48: 
49: bool ClassLoaderManager::IsLibraryValid(const std::string& library_name) {
50:   std::vector<std::string> valid_libraries = GetAllValidLibPath();
51:   return (valid_libraries.end() != std::find(valid_libraries.begin(),
52:                                              valid_libraries.end(),
53:                                              library_name));
54: }
55: 
56: bool ClassLoaderManager::LoadLibrary(const std::string& library_path) {
57:   std::lock_guard<std::mutex> lck(libpath_loader_map_mutex_);
58:   if (!IsLibraryValid(library_path)) {
59:     libpath_loader_map_[library_path] =
60:         new class_loader::ClassLoader(library_path);
61:   }
62:   return IsLibraryValid(library_path);
63: }

GetAllValidLibPath函数遍历libpath_loader_map_并把map的键放到vector容器中返回
IsLibraryValid中判断返回的vector中是否含有library_name
libpath_loader_map_[library_path] = new class_loader::ClassLoader(library_path)会创建ClassLoader对象,并放进libpath_loader_map_中
这样第一次运行时IsLibraryValid(library_path)为false

bool ClassLoaderManager::LoadLibrary(const std::string& library_path)
	bool ClassLoaderManager::IsLibraryValid(const std::string& library_name)		//首次运行=libpath_loader_map_不含有library_path,返回false
	libpath_loader_map_[library_path] = new class_loader::ClassLoader(library_path)//执行创建动作
	return bool ClassLoaderManager::IsLibraryValid(const std::string& library_name)//此时libpath_loader_map_已经有library_path,返回true

我们继续分析new class_loader::ClassLoader(library_path)

File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader.cc
21: ClassLoader::ClassLoader(const std::string& library_path)
22:     : library_path_(library_path),
23:       loadlib_ref_count_(0),
24:       classobj_ref_count_(0) {
25:   LoadLibrary();
26: }

File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader.cc
34: bool ClassLoader::LoadLibrary() {
35:   std::lock_guard<std::mutex> lck(loadlib_ref_count_mutex_);
36:   ++loadlib_ref_count_;
37:   AINFO << "Begin LoadLibrary: " << library_path_;
38:   return utility::LoadLibrary(library_path_, this);
39: }

File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.cc
194: bool LoadLibrary(const std::string& library_path, ClassLoader* loader) {
195:   if (IsLibraryLoadedByAnybody(library_path)) {
196:     AINFO << "lib has been loaded by others,only attach to class factory obj."
197:           << library_path;
198:     ClassFactoryVector lib_class_factory_objs =
199:         GetAllClassFactoryObjectsOfLibrary(library_path);
200:     for (auto& class_factory_obj : lib_class_factory_objs) {
201:       class_factory_obj->AddOwnedClassLoader(loader);
202:     }
203:     return true;
204:   }
205: 
206:   SharedLibraryPtr shared_library = nullptr;
207:   static std::recursive_mutex loader_mutex;
208:   {
209:     std::lock_guard<std::recursive_mutex> lck(loader_mutex);
210: 
211:     try {
212:       SetCurActiveClassLoader(loader);
213:       SetCurLoadingLibraryName(library_path);
214:       shared_library = SharedLibraryPtr(new SharedLibrary(library_path));
215:     } catch (const LibraryLoadException& e) {
216:       SetCurLoadingLibraryName("");
217:       SetCurActiveClassLoader(nullptr);
218:       AERROR << "LibraryLoadException: " << e.what();
219:     } catch (const LibraryAlreadyLoadedException& e) {
220:       SetCurLoadingLibraryName("");
221:       SetCurActiveClassLoader(nullptr);
222:       AERROR << "LibraryAlreadyLoadedException: " << e.what();
223:     } catch (const SymbolNotFoundException& e) {
224:       SetCurLoadingLibraryName("");
225:       SetCurActiveClassLoader(nullptr);
226:       AERROR << "SymbolNotFoundException: " << e.what();
227:     }
228: 
229:     SetCurLoadingLibraryName("");
230:     SetCurActiveClassLoader(nullptr);
231:   }
232: 
233:   if (shared_library == nullptr) {
234:     AERROR << "shared library failed: " << library_path;
235:     return false;
236:   }
237: 
238:   auto num_lib_objs = GetAllClassFactoryObjectsOfLibrary(library_path).size();
239:   if (num_lib_objs == 0) {
240:     AWARN << "Class factory objs counts is 0, maybe registerclass failed.";
241:   }
242: 
243:   std::lock_guard<std::recursive_mutex> lck(GetLibPathSharedLibMutex());
244:   LibPathSharedLibVector& opened_libraries = GetLibPathSharedLibVector();
245:   opened_libraries.emplace_back(
246:       std::pair<std::string, SharedLibraryPtr>(library_path, shared_library));
247:   return true;
248: }

File: /home/lgy/opensource/apollo/cyber/class_loader/shared_library/shared_library.cc
34: SharedLibrary::SharedLibrary(const std::string& path) { Load(path, 0); }
35: 

File: /home/lgy/opensource/apollo/cyber/class_loader/shared_library/shared_library.cc
42: void SharedLibrary::Load(const std::string& path, int flags) {
43:   std::lock_guard<std::mutex> lock(mutex_);
44:   if (handle_) throw LibraryAlreadyLoadedException(path);
45: 
46:   int real_flag = RTLD_LAZY;
47:   if (flags & SHLIB_LOCAL) {
48:     real_flag |= RTLD_LOCAL;
49:   } else {
50:     real_flag |= RTLD_GLOBAL;
51:   }
52:   handle_ = dlopen(path.c_str(), real_flag);
53:   if (!handle_) {
54:     const char* err = dlerror();
55:     throw LibraryLoadException(err ? std::string(err) : path);
56:   }
57: 
58:   path_ = path;
59: }

函数调用关系如下

ClassLoader::ClassLoader(const std::string& library_path)
	bool ClassLoader::LoadLibrary() 
		bool LoadLibrary(const std::string& library_path, ClassLoader* loader) 
			shared_library = SharedLibraryPtr(new SharedLibrary(library_path))
				void SharedLibrary::Load(const std::string& path, int flags)
					handle_ = dlopen(path.c_str(), real_flag);

经过调用终于调用了dlopen打开了动态库。

3.3.2.std::shared_ptr base = class_loader_manager_.CreateClassObj(class_name);如何创建ClassObject对象
File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader_manager.h
61: template <typename Base>
62: std::shared_ptr<Base> ClassLoaderManager::CreateClassObj(
63:     const std::string& class_name) {
64:   std::vector<ClassLoader*> class_loaders = GetAllValidClassLoaders();
65:   for (auto class_loader : class_loaders) {
66:     if (class_loader->IsClassValid<Base>(class_name)) {
67:       return (class_loader->CreateClassObj<Base>(class_name));
68:     }
69:   }
70:   AERROR << "Invalid class name: " << class_name;
71:   return std::shared_ptr<Base>();
72: }

File: /home/lgy/opensource/apollo/cyber/class_loader/class_loader.h
75: template <typename Base>
76: std::shared_ptr<Base> ClassLoader::CreateClassObj(
77:     const std::string& class_name) {
78:   if (!IsLibraryLoaded()) {
79:     LoadLibrary();
80:   }
81: 
82:   Base* class_object = utility::CreateClassObj<Base>(class_name, this);
83:   if (class_object == nullptr) {
84:     AWARN << "CreateClassObj failed, ensure class has been registered. "
85:           << "classname: " << class_name << ",lib: " << GetLibraryPath();
86:     return std::shared_ptr<Base>();
87:   }
88: 
89:   std::lock_guard<std::mutex> lck(classobj_ref_count_mutex_);
90:   classobj_ref_count_ = classobj_ref_count_ + 1;
91:   std::shared_ptr<Base> classObjSharePtr(
92:       class_object, std::bind(&ClassLoader::OnClassObjDeleter<Base>, this,
93:                               std::placeholders::_1));
94:   return classObjSharePtr;
95: }


File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_loader_utility.h
94: template <typename Base>
95: Base* CreateClassObj(const std::string& class_name, ClassLoader* loader) {
96:   GetClassFactoryMapMapMutex().lock();
97:   ClassClassFactoryMap& factoryMap =
98:       GetClassFactoryMapByBaseClass(typeid(Base).name());
99:   AbstractClassFactory<Base>* factory = nullptr;
100:   if (factoryMap.find(class_name) != factoryMap.end()) {
101:     factory = dynamic_cast<utility::AbstractClassFactory<Base>*>(
102:         factoryMap[class_name]);
103:   }
104:   GetClassFactoryMapMapMutex().unlock();
105: 
106:   Base* classobj = nullptr;
107:   if (factory && factory->IsOwnedBy(loader)) {
108:     classobj = factory->CreateObj();
109:   }
110: 
111:   return classobj;
112: }


File: /home/lgy/opensource/apollo/cyber/class_loader/utility/class_factory.h
69: template <typename ClassObject, typename Base>
70: class ClassFactory : public AbstractClassFactory<Base> {
71:  public:
72:   ClassFactory(const std::string& class_name,
73:                const std::string& base_class_name)
74:       : AbstractClassFactory<Base>(class_name, base_class_name) {}
75: 
76:   Base* CreateObj() const { return new ClassObject; }
77: };

函数调用关系如下:

template <typename Base> std::shared_ptr<Base> ClassLoaderManager::CreateClassObj(const std::string& class_name);
	template <typename Base> std::shared_ptr<Base> ClassLoader::CreateClassObj(const std::string& class_name) 
		template <typename Base> Base* CreateClassObj(const std::string& class_name, ClassLoader* loader)
 			template <typename ClassObject, typename Base> class ClassFactory : public AbstractClassFactory<Base>
			{
				Base* CreateObj() const { return new ClassObject; }
			}

经过一路调用终于创建了ClassObject,就本例子而言生成了一个CommonComponentSample对象。

3.3.3.base->Initialize(component.config());又做了什么?

从上部分我们知道base是CommonComponentSample对象。那Initialize又是哪里定义的呢?

File: /home/lgy/opensource/apollo/cyber/component/component_base.h
41: class ComponentBase : public std::enable_shared_from_this<ComponentBase> {
	...
47: 
48:   virtual bool Initialize(const ComponentConfig& config) { return false; }
49:   virtual bool Initialize(const TimerComponentConfig& config) { return false; }
	...
}

File: /home/lgy/opensource/apollo/cyber/component/component.h
56: template <typename M0 = NullType, typename M1 = NullType,
57:           typename M2 = NullType, typename M3 = NullType>
58: class Component : public ComponentBase {
59:  public:
	...
70:   bool Initialize(const ComponentConfig& config) override;
	...
}


File: /home/lgy/opensource/apollo/cyber/component/component.h
112: template <typename M0, typename M1>
113: class Component<M0, M1, NullType, NullType> : public ComponentBase {
114:  public:
		...
117:   bool Initialize(const ComponentConfig& config) override;
		...
124: };


File: /home/lgy/opensource/apollo/cyber/component/component.h
231: template <typename M0, typename M1>
232: bool Component<M0, M1, NullType, NullType>::Initialize(
233:     const ComponentConfig& config) {
234:   node_.reset(new Node(config.name()));
235:   LoadConfigFiles(config);
236: 
237:   if (config.readers_size() < 2) {
238:     AERROR << "Invalid config file: too few readers.";
239:     return false;
240:   }
241: 
242:   if (!Init()) {
243:     AERROR << "Component Init() failed.";
244:     return false;
245:   }
246: 
247:   bool is_reality_mode = GlobalData::Instance()->IsRealityMode();
248: 
249:   ReaderConfig reader_cfg;
250:   reader_cfg.channel_name = config.readers(1).channel();
251:   reader_cfg.qos_profile.CopyFrom(config.readers(1).qos_profile());
252:   reader_cfg.pending_queue_size = config.readers(1).pending_queue_size();
253: 
254:   auto reader1 = node_->template CreateReader<M1>(reader_cfg);
255: 
256:   reader_cfg.channel_name = config.readers(0).channel();
257:   reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile());
258:   reader_cfg.pending_queue_size = config.readers(0).pending_queue_size();
259: 
260:   std::shared_ptr<Reader<M0>> reader0 = nullptr;
261:   if (cyber_likely(is_reality_mode)) {
262:     reader0 = node_->template CreateReader<M0>(reader_cfg);
263:   } else {
264:     std::weak_ptr<Component<M0, M1>> self =
265:         std::dynamic_pointer_cast<Component<M0, M1>>(shared_from_this());
266: 
267:     auto blocker1 = blocker::BlockerManager::Instance()->GetBlocker<M1>(
268:         config.readers(1).channel());
269: 
270:     auto func = [self, blocker1](const std::shared_ptr<M0>& msg0) {
271:       auto ptr = self.lock();
272:       if (ptr) {
273:         if (!blocker1->IsPublishedEmpty()) {
274:           auto msg1 = blocker1->GetLatestPublishedPtr();
275:           ptr->Process(msg0, msg1);
276:         }
277:       } else {
278:         AERROR << "Component object has been destroyed.";
279:       }
280:     };
281: 
282:     reader0 = node_->template CreateReader<M0>(reader_cfg, func);
283:   }
284:   if (reader0 == nullptr || reader1 == nullptr) {
285:     AERROR << "Component create reader failed.";
286:     return false;
287:   }
288:   readers_.push_back(std::move(reader0));
289:   readers_.push_back(std::move(reader1));
290: 
291:   if (cyber_unlikely(!is_reality_mode)) {
292:     return true;
293:   }
294: 
295:   auto sched = scheduler::Instance();
296:   std::weak_ptr<Component<M0, M1>> self =
297:       std::dynamic_pointer_cast<Component<M0, M1>>(shared_from_this());
298:   auto func = [self](const std::shared_ptr<M0>& msg0,
299:                      const std::shared_ptr<M1>& msg1) {
300:     auto ptr = self.lock();
301:     if (ptr) {
302:       ptr->Process(msg0, msg1);
303:     } else {
304:       AERROR << "Component object has been destroyed.";
305:     }
306:   };
307: 
308:   std::vector<data::VisitorConfig> config_list;
309:   for (auto& reader : readers_) {
310:     config_list.emplace_back(reader->ChannelId(), reader->PendingQueueSize());
311:   }
312:   auto dv = std::make_shared<data::DataVisitor<M0, M1>>(config_list);
313:   croutine::RoutineFactory factory =
314:       croutine::CreateRoutineFactory<M0, M1>(func, dv);
315:   return sched->CreateTask(factory, node_->Name());
316: }

从上述代码我们可以看出,ComponentBase基类定义了Initialize,经过继承Component<M0, M1, NullType, NullType>::Initialize特化定义完成。
Component<M0, M1, NullType, NullType>::Initialize主要调用如下方法:

	Init();
	auto reader1 = node_->template CreateReader<M1>(reader_cfg);
	reader0 = node_->template CreateReader<M0>(reader_cfg, func);
	auto dv = std::make_shared<data::DataVisitor<M0, M1>>(config_list);
	croutine::RoutineFactory factory = croutine::CreateRoutineFactory<M0, M1>(func, dv);
	return sched->CreateTask(factory, node_->Name());

完成read0 reader1的创建,创建RoutineFactory,创建CreateTask,其中func源码如下:

298:   auto func = [self](const std::shared_ptr<M0>& msg0,
299:                      const std::shared_ptr<M1>& msg1) {
300:     auto ptr = self.lock();
301:     if (ptr) {
302:       ptr->Process(msg0, msg1);
303:     } else {
304:       AERROR << "Component object has been destroyed.";
305:     }
306:   };

猜测后续程序调用会执行Process,具体如何执行后续文章再做分析。假设Process得到了调用,继续向下分析:

File: /home/lgy/opensource/apollo/cyber/component/component.h
222: template <typename M0, typename M1>
223: bool Component<M0, M1, NullType, NullType>::Process(
224:     const std::shared_ptr<M0>& msg0, const std::shared_ptr<M1>& msg1) {
225:   if (is_shutdown_.load()) {
226:     return true;
227:   }
228:   return Proc(msg0, msg1);
229: }

File: /home/lgy/opensource/apollo/cyber/examples/common_component_example/common_component_example.cc
23: bool CommonComponentSample::Proc(const std::shared_ptr<Driver>& msg0,
24:                                  const std::shared_ptr<Driver>& msg1) {
25:   AINFO << "Start common component Proc [" << msg0->msg_id() << "] ["
26:         << msg1->msg_id() << "]";
27:   return true;
28: }

这样就回调用到用户写的Proc方法了。

我们做一些总结:
实现节点:比如CommonComponentSample,用户程序只需要实现Init以及Proc方法就完成了节点的代码。
启动节点:比如使用mainboard -d /apollo/cyber/examples/common_component_example/common.dag,其中mainboard是执行程序,-d指定一个dag文件,里面配置了节点的基本信息。
运行用户的程序:启动节点时运行Initialize,然后调用Init,从而调用用户的初始化代码;系统调度器会调用Process方法,再调用Proc方法实现用户程序的调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值