OpenCascade源码剖析:Handle类

news2024/11/18 4:25:17

Handle其实就是智能指针的上古版本,了解一点C++11的应该对shared_ptr非常熟悉,那么你就把Handle当做shared_ptr来理解就没有任何问题了。

不过OCCT的Handles是侵入式的实现,前面讲过Standard_Transient类提供了引用计数机制,这个就是为了实现Handle

定义Handle

在需要使用Handle的类中,通过宏DEFINE_STANDARD_HANDLE(class_name,ancestor_name)来定义这个类的Hanle,例如给TopoDS_TShape定义一个Handle:

此宏展开后代码如下,可以看到,次宏定义了一个Handle_TopoDS_TShape类,不过这个类是个空壳,其实现基本在基类opencascade::handle<TopoDS_TShape>

class Handle_TopoDS_TShape : public opencascade::handle<TopoDS_TShape> 
{ 
public: 
    Handle_TopoDS_TShape() {} 
    Handle_TopoDS_TShape(opencascade::handle<TopoDS_TShape>&& theHandle) : opencascade::handle<TopoDS_TShape>(theHandle) 
    {
    } 
    template <class T2, typename = typename std::enable_if <std::is_base_of <TopoDS_TShape,T2>::value>::type> 
    inline Handle_TopoDS_TShape(const opencascade::handle<T2>& theOther) : opencascade::handle<TopoDS_TShape>(theOther) 
    {
    } 
    template <class T2, typename = typename std::enable_if <std::is_base_of <TopoDS_TShape,T2>::value>::type> 
    inline Handle_TopoDS_TShape(const T2* theOther) : opencascade::handle<TopoDS_TShape>(theOther) 
    {
    } 
    template<typename T> inline Handle_TopoDS_TShape& operator=(T theOther) 
    { 
        opencascade::handle<TopoDS_TShape>::operator=(theOther);  
        return *this; 
    } 
};

Handle的实现

opencascade::handle是一个模板类,该类实现了共享智能指针的基本功能

  • BeginScope,EndScope用于更新引用计数,管理生命周期
  • 拷贝,赋值,移动,逻辑运算等函数或运算符的实现
  • DownCast类型转换,向上类型转换
namespace opencascade {

  template <class T>
  class handle
  {
  public:
    typedef T element_type;

  public:
    handle () : entity(0) {}

    handle (const T *thePtr) : entity(const_cast<T*>(thePtr))
    {
      BeginScope();
    }

    handle (const handle& theHandle) : entity(theHandle.entity)
    {
      BeginScope();
    }

    handle (handle&& theHandle) noexcept : entity(theHandle.entity)
    {
      theHandle.entity = 0;
    }

    ~handle ()
    {
      EndScope();
    }

    void Nullify()
    {
      EndScope();
    }

    bool IsNull() const { return entity == 0; } 

    void reset (T* thePtr)
    {
      Assign (thePtr);
    }

    handle& operator= (const handle& theHandle)
    {
      Assign (theHandle.entity);
      return *this;
    }

    handle& operator= (const T* thePtr)
    {
      Assign (const_cast<T*>(thePtr));
      return *this;
    }

    handle& operator= (handle&& theHandle) noexcept
    {
      std::swap (this->entity, theHandle.entity);
      return *this;
    }

    T* get() const { return static_cast<T*>(this->entity); }

    T* operator-> () const { return static_cast<T*>(this->entity); }

    T& operator* () const { return *get(); }

    template <class T2>
    bool operator== (const handle<T2>& theHandle) const
    { 
      return get() == theHandle.get();
    }

    template <class T2>
    bool operator== (const T2 *thePtr) const
    { 
      return get() == thePtr;
    }

    template <class T2>
    friend bool operator== (const T2 *left, const handle& right)
    {
      return left == right.get();
    }

    template <class T2>
    bool operator!= (const handle<T2>& theHandle) const
    {
      return get() != theHandle.get();
    }

    template <class T2>
    bool operator!= (const T2 *thePtr) const
    {
      return get() != thePtr;
    }

    template <class T2>
    friend bool operator!= (const T2 *left, const handle& right)
    {
      return left != right.get();
    }

    template <class T2>
    bool operator< (const handle<T2>& theHandle) const
    { 
      return get() < theHandle.get();
    }

    template <class T2>
    static typename opencascade::std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type
      DownCast (const handle<T2>& theObject)
    {
      return handle (dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
    }

    template <class T2>
    static typename opencascade::std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type 
      DownCast (const T2* thePtr)
    {
      return handle (dynamic_cast<T*>(const_cast<T2*>(thePtr)));
    }

    template <class T2>
    __declspec(deprecated("down-casting from object of the same or unrelated type is meaningless"))
    static handle DownCast (const handle<T2>& theObject, typename opencascade::std::enable_if<!is_base_but_not_same<T2, T>::value, void*>::type = 0)
    {
      return handle (dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
    }

    template <class T2>
    __declspec(deprecated("down-casting from object of the same or unrelated type is meaningless"))
    static handle DownCast (const T2* thePtr, typename opencascade::std::enable_if<!is_base_but_not_same<T2, T>::value, void*>::type = 0)
    {
      return handle (dynamic_cast<T*>(const_cast<T2*>(thePtr)));
    }

    explicit operator bool () const
    { 
      return entity != nullptr;
    }

    template <class T2, typename = typename std::enable_if<is_base_but_not_same<T2, T>::value>::type>
    operator const handle<T2>& () const
    {
      return reinterpret_cast<const handle<T2>&>(*this);
    }

    template <class T2, typename = typename std::enable_if<is_base_but_not_same<T2, T>::value>::type>
    operator handle<T2>& ()
    {
      return reinterpret_cast<handle<T2>&>(*this);
    }

  private:
    void Assign (Standard_Transient *thePtr)
    {
      if (thePtr == entity)
        return;
      EndScope();
      entity = thePtr;
      BeginScope();
    }

    void BeginScope()
    {
      if (entity != 0)
        entity->IncrementRefCounter();
    }

    void EndScope()
    {
      if (entity != 0 && entity->DecrementRefCounter() == 0)
        entity->Delete();
      entity = 0;
    }

    template <class T2> friend class handle;

  private:
    Standard_Transient* entity;
  };
} 

至于为什么需要弄一个Handle_TopoDS_TShape空壳类而不是直接模板实现就可以(一般只能指针都是一个模板类即可),应该是历史包袱问题,毕竟上古时期,编译器可能都不太支持模板。

Handle的一些问题

循环引用

标准库外的野鸡版本共享智能指针基本上都会有头疼的循环依赖问题,毕竟C++也是到了21世纪20年代才通过引入一个weak_ptr才解决shared_ptr的循环引用问题,这也不是大问题,避免循环依赖,或者手动打断依赖即可

性能问题

  • 避免频繁down cast
  • 避免拷贝

线程安全

Handle不是线程安全的,所以,上锁吧?

类型转换

DownCast的实现是dynamic_cast,这个就有点半拉子了,上篇讲到Standard_Transient自己实现了RTTI,而dynamic_cast依托于C++自带的RTTI,相当于双重性能消耗。一般追求性能的系统,自己实现RTTI时,可以实现安全的Cast函数,并且禁用dynamic_cast。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1501281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新质生产力助春播春管:佳格天地连续第5年上线大数据平台,服务春季生产

随着“惊蛰”节气过去,全国各地陆续掀起春播春管热潮。今年的政府工作报告中指出,2023年我国粮食产量1.39万亿斤,再创新高。2024年要坚持不懈抓好“三农”工作,扎实推进乡村全面振兴,粮食产量预期目标1.3万亿斤以上。 粮食产量预期目标的明确为一年农事生产指引了方向。同时,新…

地址分词 | EXCEL批量进行地址分词,标准化为十一级地址

一 需求 物流需要对用户输入地址进行检查&#xff0c;受用户录入习惯地址可能存在多种问题。 地址标准化是基于地址引擎和地址大数据模型&#xff0c;自动将地址信息标准化为省、市、区市县、街镇、小区、楼栋、单元、楼层、房屋、房间等元素&#xff0c;补充层级缺失数据、构建…

导出谷歌gemma模型为ONNX

参考代码如下&#xff08;从GitHub - luchangli03/export_llama_to_onnx: export llama to onnx修改而来&#xff0c;后面会合入进去&#xff09; 模型权重链接参考&#xff1a; https://huggingface.co/google/gemma-2b-it 可以对modeling_gemma.py进行一些修改(transforme…

LLCC68与SX1278 LoRa模块的优势对比?

LLCC68和SX1278都是Semtech公司推出的LoRa调制解调器模块&#xff0c;属于LoRa模块家族。它们在无线通信领域都有着广泛的应用&#xff0c;但具体的优势会取决于具体的应用场景和需求。下面是对LLCC68和SX1278 LoRa模块的一些优势对比&#xff1a; LLCC68 LoRa模块的优势&#…

qt自定义时间选择控件窗口

效果如图&#xff1a; 布局如图&#xff1a; 参考代码&#xff1a; //DateTimeSelectWidget #ifndef DATETIMESELECTWIDGET_H #define DATETIMESELECTWIDGET_H#include <QWidget> #include <QDateTime>namespace Ui { class DateTimeSelectWidget; }class DateTim…

【手游联运平台搭建】游戏平台的作用

随着科技的不断发展&#xff0c;游戏行业也在不断壮大&#xff0c;而游戏平台作为连接玩家与游戏的桥梁&#xff0c;发挥着越来越重要的作用。游戏平台不仅为玩家提供了便捷的游戏体验&#xff0c;还为游戏开发者提供了广阔的市场和推广渠道。本文将从多个方面探讨游戏平台的作…

扩展CArray类,增加Contain函数

CArray不包含查找类的函数&#xff0c;使用不便。考虑扩展CArray类&#xff0c;增加Contain函数&#xff0c;通过回调函数暴露数组元素的比较方法&#xff0c;由外部定义。该方法相对重载数组元素的“”符号更加灵活&#xff0c;可以根据需要配置不同的回调函数进行比较 //类型…

继深圳后,重庆与鸿蒙展开原生应用开发合作

截至2023年底&#xff0c;开源鸿蒙开源社区已有250多家生态伙伴加入&#xff0c;开源鸿蒙项目捐赠人达35家&#xff0c;通过开源鸿蒙兼容性测评的伙伴达173个&#xff0c;累计落地230余款商用设备&#xff0c;涵盖金融、教育、智能家居、交通、数字政府、工业、医疗等各领域。 …

底层day3作业

思维导图 作业&#xff1a;1.总结任务的调度算法&#xff0c;把实现代码再写一下 算法&#xff1a;抢占式调度时间片轮转 1.抢占式调度&#xff1a;任务优先级高的可以打断任务优先级低的执行&#xff08;适用于不同优先级&#xff09; 2.时间片轮转&#xff1a;每一个任务拥…

react的diff源码

react 的 render 阶段&#xff0c;其中 begin 时会调用 reconcileChildren 函数&#xff0c; reconcileChildren 中做的事情就是 react 知名的 diff 过程 diff 算法介绍 react 的每次更新&#xff0c;都会将新的 ReactElement 内容与旧的 fiber 树作对比&#xff0c;比较出它们…

电脑小问题:Windows更新后黑屏

Windows 更新后黑屏解决方法 在 Windows 更新后&#xff0c;伴随了一个小问题&#xff0c;电脑启动后出现了桌面黑屏。原因可能是火绒把 explorer.exe 当病毒处理了。 下面讲解 Windows 更新后黑屏的解决方法&#xff0c;步骤如下&#xff1a; 1. 按 ctrl alt delete 组合键…

基于Python3的数据结构与算法 - 12 数据结构(列表和栈)

目录 一、引入 二、分类 三、列表 1. C语言中数组的存储方式 2. Python中列表的存储方式 四、栈 1. 栈的应用 -- 括号匹配问题 一、引入 定义&#xff1a;数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单来说&#x…

portainer管理远程docker和docker-swarm集群

使用前请先安装docker和docker-compose&#xff0c;同时完成docker-swarm集群初始化 一、portainer-ce部署 部署portainer-ce实时管理本机docker&#xff0c;使用docker-compose一键拉起 docker-compose.yml version: 3 services:portainer:container_name: portainer#imag…

Docker上部署LPG(loki+promtail+grafana)踩坑复盘

Docker上部署LPG&#xff08;lokipromtailgrafana&#xff09;踩坑复盘 声明网上配置部署踩坑 声明 参考掘金文章&#xff1a;https://juejin.cn/post/7008424451704356872 版本高的用docker compose命令&#xff0c;版本低的用docker-compose 按照文章描述&#xff0c;主要准备…

UVA378 Intersecting Lines 题解

UVA378 Intersecting Lines 题解 怎么这么多点斜式邪教啊。 解法 在计算几何中&#xff0c;我们应该尽可能地避免使用浮点数的计算&#xff0c;尽可能地使用向量计算。 本篇题解默认读者具有向量基础。 为了方便讲解&#xff0c;我们将输入的四个点分别记作 A , B , C , …

本鲸多方位助力创业者高效对接创新创业机遇

在科技创新的浪潮中&#xff0c;创业者们不断探索着新的商业机会&#xff0c;寻求着创新创业的道路。然而&#xff0c;面对复杂多变的市场环境和激烈的竞争压力&#xff0c;如何高效对接创新创业机遇成为了摆在创业者面前的重要课题。 本鲸依托海南本鲸投资有限公司和重庆本鲸…

关于Vivado的实施过程、SDC和XDC约束支持、Vivado实施子流程、Tcl API支持脚本

关于Vivado的实施过程 AMD Vivado™设计套件可实现以下AMD设备体系结构&#xff1a;AMD Versal™自适应计算加速平台&#xff08;自适应SoC&#xff09;&#xff0c;AMDUltraScale™、AMD UltraScale™和AMD 7系列FPGA。各种设计来源如下支持&#xff0c;包括&#xff1a; •…

WebGPU vs. 像素流

在构建 Bzar 之前&#xff0c;我们讨论过我们的技术栈是基于在云上渲染内容的像素流&#xff0c;还是基于使用设备自身计算能力的本地渲染技术。 由于这种选择会极大地影响项目的成本、可扩展性和用户体验&#xff0c;因此在开始编写一行代码之前&#xff0c;从一开始就采取正确…

typeorm-入门

简述 typeorm是一个数据库orm框架&#xff0c;在nestjs官网中有提到&#xff0c;可以充分发挥利用typescript的特性&#xff0c;当然也支持js其中涉及的概念包括 DataSource 数据源&#xff0c;Connection 连接数据库Entity 实体&#xff0c;实体类映射数据库表Relation 关系…

30个炫酷光效视频转场PR模板剪辑素材下载

视频转场Premiere模板&#xff0c;包含30个炫酷光效视频转场过渡效果PR项目模板下载。 适用软件&#xff1a;Premiere Pro 2023 | 分辨率&#xff1a;3840x2160 (4K) | 无需插件 | 文件大小&#xff1a;56.33MB 来自PR转场&#xff0c;下载地址&#xff1a;https://prmuban.com…