研发三维GIS系统笔记/框架改造/智能指针重构框架-003
1. 使用智能指针重构系统
原有的系统都是裸指针,在跨模块与多线程中使用裸指针管理起来很麻烦,尤其是多任务系统中会出现野指针
1 class CELLTileTask :public CELLTask 2 { 3 public: 4 CELLQuadTree* _node; 5 TileId _tileId; 6 CELLImage _image; 7 };
任务队列中存储了 CELLQuadTree* _node; 在频繁或者剧烈操作相机的情况下,造成大量的瓦片任务,同时瓦片任务中存储的对四叉树对象已经被释放
在进行使用的过程中,就会出现野指针,为了避免这些问题,引入智能指针来解决对象的生命周期的问题。避免野指针的出现。
2. 基类对象改造
基类对象是被引擎中的所有其他的类继承使用,所以先改造基类,从基类开始支持智能指针。
1 class CELLObject :public std::enable_shared_from_this<CELLObject> 2 { 3 public: 4 using ObjectPtr = std::shared_ptr<CELLObject>; 5 public: 6 CELLObject() 7 {} 8 virtual ~CELLObject() 9 {} 10 ObjectPtr ptr() 11 { 12 return shared_from_this(); 13 } 14 15 template<class T> 16 std::shared_ptr<T> toPtr() 17 { 18 return std::dynamic_pointer_cast<T>(ptr()); 19 } 20 };
好处1,std::enable_shared_from_this<CELLObject> 这一句很重要,这样对象中继承了智能指针中的引用计数对象,降低访存次数,提升效率
好处2:可以实现智能指针与裸指针的相互转化,可以从裸指针转换成智能指针。
3. 改造代码
引擎中四叉树节点
using NodePtr = std::shared_ptr<CELLQuadTree>;
class CELLQuadTree :public CELLObject { public: enum ChildId { CHILD_LT, CHILD_RT, CHILD_LB, CHILD_RB, }; enum { FLAG_HAS_IMAGE = 1<<0, FLAG_HAS_CULL = 1<<1, FLAG_RENDER = 1<<2, }; public: typedef std::vector<CELLQuadTree*> ArrayNode; typedef CELLTerrainInterface TerrainApi; using NodePtr = std::shared_ptr<CELLQuadTree>; public: TerrainApi* _terrain; /// 数据标志 uint _flag; /// 对应瓦片id TileId _tileId; real2 _vStart; real2 _vEnd; float2 _uvStart; float2 _uvEnd; /// 对应瓦片的范围(世界坐标) aabb3dr _aabb; /// 位置 ChildId _cornerId; /// 当前瓦片的父节点,这里不能使用智能指针,否则会造成相互引用,造成智能指针无法释放(相互依赖引用) CELLQuadTree* _parent; /// 瓦片的孩子节点,注意这里,使用了智能指针 NodePtr _childs[4]; /// 纹理id uint _textureId; };
4. 节点示释放代码,不在使用delete 操作
for (int i = 0 ;i < 4 ; ++ i) { _childs[i] = nullptr; }
5. 任务系统改造,使用智能指针对象
1 class CELLTask :public CELLObject 2 { 3 public: 4 CELLTask() 5 {} 6 virtual ~CELLTask() 7 {} 8 }; 9 10 using TaskPtr = std::shared_ptr<CELLTask>;
6. 任务对象
1 class CELLTaskSystem 2 { 3 public: 4 class TaskThread :public CELLThread 5 { 6 public: 7 bool _exitFlag; 8 CELLTaskSystem* _system; 9 public: 10 TaskThread(CELLTaskSystem* pSystem) 11 { 12 _system = pSystem; 13 _exitFlag = true; 14 } 15 public: 16 virtual void join() 17 { 18 _exitFlag = true; 19 CELLThread::join(); 20 21 } 22 virtual bool onCreate() 23 { 24 _exitFlag = false; 25 return false; 26 } 27 virtual bool onRun() 28 { 29 while (!_exitFlag) 30 { 31 _system->run(); 32 } 33 return false; 34 } 35 virtual bool onDestroy() 36 { 37 return false; 38 } 39 }; 40 41 typedef std::vector<CELLThread*> ArrayThread; 42 typedef std::list<TaskPtr> ArrayTask; 43 public: 44 CELLTaskObserver* _observer; 45 ArrayThread _threads;
/// 这里使用智能指针队列,而不是裸指针 46 ArrayTask _tasks; 47 CELLSemaphore _semphore; 48 CELLMutex _mutex; 49 };