前言
总结了一下CarlaUE5的整体代码架构,该总结基于以下代码:
- repo: https://github.com/carla-simulator/carla.git
- branch:
ue5-dev - commit:
141a8a2
整体架构

Server架构

Client架构

PythonAPI

一些C++知识点
weak_ptr
- motivation:只有
shared_ptr的话会出现循环引用的问题 - 具体来说,就是搞一个阉割版的,不会影响计数的“智能指针”,也就是
weak_ptr了 weak_ptr不能直接用,只能先通过.lock()提级(构造)为shared_ptr之后再用- 这个blog和这个blog讲解得挺好的
atomic
- motivation:针对变量的高效线程安全读写工具
- 相比
lock,mutex这些要跟跟内核打交道(有用户态和内核态的切换开销)的多线程工具,atomic属于硬件指令集的工具,效率更高 - 对于
atomic<int> ai;,需要调用ai.load()和ai.store(1)进行读写 - 又由于编译器会对代码的实际执行顺序进行优化,
atomic提供了一些指令去控制代码的执行顺序,具体可以参考这个blog
enable_shared_from_this
- motivation:使得成员函数使用
shared_ptr<T>(this)成为可能。假如没有额外支持的话,成员函数直接裸使用shared_ptr<T>(this)会导致this被析构两次 - 核心要做的事情就是使得对象知道管理自己的
shared_ptr是什么。具体来说:esft是个模板类,我们需要继承他。这个类里有一个weak_ptr成员,语意是指向管理本对象的shared_ptr;同时会提供一个shared_from_this方法,去调用weak_ptr.lock()- 在调用
make_shared的时候,会调用dynamic_cast来检查当前要构造的对象是否继承自esft,假如是,就会将其weak_ptr对象指向shared_ptr
- 关于这部分,可以参考这个blog
mutable
- motivation:允许
const成员函数修改的成员变量
pImpl
- motivation
- 完全隐藏实现细节
- 避免修改成员变量引起头文件变化
- 具体来说,就是
- 在类的
private里面前向声明一个Impl类 - 成员变量只保留一个指向
Impl类的unique_ptr
- 在类的
compare_exchange
- motivation:解决多线程编程时,读到的值在要用的时候可能已经被修改的问题,主要用于条件赋值,否则直接用
store就好了 - 思路就是在用的时候再验一下货。具体来说,就是搞了一个包含比较和赋值这两个指令的原子操作,只有当
self跟expected相等的时候,self才会被赋值为target - 这个也被叫做CAS(Compare and Swap),属于无锁编程的概念。
- 可以参考这个blog