研发三维GIS系统笔记/框架改造/智能指针重构框架-003

发布时间 2023-10-08 18:36:26作者: 经纬视界

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 };