Q_GLOBAL_STATIC宏
文章目录
- 目的
- Q_GLOBAL_STATIC
- 源代码分析
- 涉及到原子操作 以及静态变量初始化顺序
- 代码实现
目的
由Q_GLOBAL_STATIC宏, 引发的基于线程安全的Qt 单例模式的使用。
Q_GLOBAL_STATIC
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/#include <QtCore/qglobal.h>#ifndef QGLOBALSTATIC_H
#define QGLOBALSTATIC_H#include <QtCore/qatomic.h>QT_BEGIN_NAMESPACEnamespace QtGlobalStatic {
enum GuardValues {Destroyed = -2,Initialized = -1,Uninitialized = 0,Initializing = 1
};
}#if !QT_CONFIG(thread) || defined(Q_COMPILER_THREADSAFE_STATICS)
// some compilers support thread-safe statics
// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4
// support it. C++11 also requires this behavior.
// Clang and Intel CC masquerade as GCC when compiling on Linux.
//
// Apple's libc++abi however uses a global lock for initializing local statics,
// which will block other threads also trying to initialize a local static
// until the constructor returns ...
// We better avoid these kind of problems by using our own locked implementation.#if defined(Q_OS_UNIX) && defined(Q_CC_INTEL)
// Work around Intel issue ID 6000058488:
// local statics inside an inline function inside an anonymous namespace are global
// symbols (this affects the IA-64 C++ ABI, so OS X and Linux only)
# define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN
#else
# define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN inline
#endif#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \Q_GLOBAL_STATIC_INTERNAL_DECORATION Type *innerFunction() \{ \struct HolderBase { \~HolderBase() noexcept \{ if (guard.loadRelaxed() == QtGlobalStatic::Initialized) \guard.storeRelaxed(QtGlobalStatic::Destroyed); } \}; \static struct Holder : public HolderBase { \Type value; \Holder() \noexcept(noexcept(Type ARGS)) \: value ARGS \{ guard.storeRelaxed(QtGlobalStatic::Initialized); } \} holder; \return &holder.value; \}
#else
// We don't know if this compiler supports thread-safe global statics
// so use our own locked implementationQT_END_NAMESPACE
#include <QtCore/qmutex.h>
#include <mutex>
QT_BEGIN_NAMESPACE#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \Q_DECL_HIDDEN inline Type *innerFunction() \{ \static Type *d; \static QBasicMutex mutex; \int x = guard.loadAcquire(); \if (Q_UNLIKELY(x >= QtGlobalStatic::Uninitialized)) { \const std::lock_guard<QBasicMutex> locker(mutex); \if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) { \d = new Type ARGS; \static struct Cleanup { \~Cleanup() { \delete d; \guard.storeRelaxed(QtGlobalStatic::Destroyed); \} \} cleanup; \guard.storeRelease(QtGlobalStatic::Initialized); \} \} \return d; \}
#endif// this class must be POD, unless the compiler supports thread-safe statics
template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard>
struct QGlobalStatic
{typedef T Type;bool isDestroyed() const { return guard.loadRelaxed() <= QtGlobalStatic::Destroyed; }bool exists() const { return guard.loadRelaxed() == QtGlobalStatic::Initialized; }operator Type *() { if (isDestroyed()) return nullptr; return innerFunction(); }Type *operator()() { if (isDestroyed()) return nullptr; return innerFunction(); }Type *operator->(){Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");return innerFunction();}Type &operator*(){Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");return *innerFunction();}
};#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \namespace { namespace Q_QGS_ ## NAME { \typedef TYPE Type; \QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized); \Q_GLOBAL_STATIC_INTERNAL(ARGS) \} } \static QGlobalStatic<TYPE, \Q_QGS_ ## NAME::innerFunction, \Q_QGS_ ## NAME::guard> NAME;#define Q_GLOBAL_STATIC(TYPE, NAME) \Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())QT_END_NAMESPACE
#endif // QGLOBALSTATIC_H
源代码分析
Q_GLOBAL_STATIC
用于定义全局静态变量
#define Q_GLOBAL_STATIC(TYPE, NAME) \Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
Q_GLOBAL_STATIC_WITH_ARGS
带有参数的全局静态变量宏
在匿名命名空间内定义了命名空间Q_QGS_ ## NAME,该命名空间内定义了
- 类型:typedef TYPE Type
- 原子操作变量:QBasicAtomicInt guard 初始化QtGlobalStatic::Uninitialized
- 内联函数:Type *innerFunction()
通过类模板QGlobalStatic来定义全局静态变量 NAME
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \namespace { namespace Q_QGS_ ## NAME { \typedef TYPE Type; \QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized); \Q_GLOBAL_STATIC_INTERNAL(ARGS) \} } \static QGlobalStatic<TYPE, \Q_QGS_ ## NAME::innerFunction, \Q_QGS_ ## NAME::guard> NAME;
内联函数innerFunction
enum GuardValues {Destroyed = -2,Initialized = -1,Uninitialized = 0,Initializing = 1
};#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \Q_GLOBAL_STATIC_INTERNAL_DECORATION Type *innerFunction() \{ \struct HolderBase { \~HolderBase() noexcept \{ if (guard.loadRelaxed() == QtGlobalStatic::Initialized) \guard.storeRelaxed(QtGlobalStatic::Destroyed); } \}; \static struct Holder : public HolderBase { \Type value; \Holder() \noexcept(noexcept(Type ARGS)) \: value ARGS \{ guard.storeRelaxed(QtGlobalStatic::Initialized); } \} holder; \return &holder.value; \}
#else
// We don't know if this compiler supports thread-safe global statics
// so use our own locked implementationQT_END_NAMESPACE
#include <QtCore/qmutex.h>
#include <mutex>
QT_BEGIN_NAMESPACE
采用双重检查方式来初始化全局静态变量
#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \Q_DECL_HIDDEN inline Type *innerFunction() \{ \static Type *d; \static QBasicMutex mutex; \int x = guard.loadAcquire(); \if (Q_UNLIKELY(x >= QtGlobalStatic::Uninitialized)) { \const std::lock_guard<QBasicMutex> locker(mutex); \if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) { \d = new Type ARGS; \static struct Cleanup { \~Cleanup() { \delete d; \guard.storeRelaxed(QtGlobalStatic::Destroyed); \} \} cleanup; \guard.storeRelease(QtGlobalStatic::Initialized); \} \} \return d; \}
#endif
涉及到原子操作 以及静态变量初始化顺序
atomic
atomic_load与atomic_store
Load是C++11标准的介绍
用于原子访问全局和静态变量的新加载和存储操作。
load操作可以保证多线程环境下全局变量和静态变量的原子加载,
避免数据竞争和线程不安全问题
静态变量初始化顺序
- 全局变量初始化在主函数之前
- 静态局部变量初始化在第一次调用这个静态局部变量时
代码实现
mainwindow.h
static MainWindow* getInstance();
mainwindow.cpp
Q_GLOBAL_STATIC(MainWindow,mainwindow)static MainWindow* MainWindow::getInstance(){return mainwindow();
}
相关文章:
Q_GLOBAL_STATIC宏
文章目录 目的Q_GLOBAL_STATIC源代码分析涉及到原子操作 以及静态变量初始化顺序代码实现 目的 由Q_GLOBAL_STATIC宏, 引发的基于线程安全的Qt 单例模式的使用。 Q_GLOBAL_STATIC /***************************************************************************…...
[批处理]_[初级]_[如何删除变量值里的双引号]
场景 在使用Visual Studio开发本地程序的时,需要在项目属性,生成事件->生成后事件里增加一些资源的打包,复制,删除等操作,那么就需要用到批处理来进行。而传递带空格的路径给外部的批处理文件时就需要双引号引用从…...
51单片机电子钟闹钟温度LCD1602液晶显示设计( proteus仿真+程序+原理图+设计报告+讲解视频)
51单片机电子钟闹钟温度液晶显示设计( proteus仿真程序原理图设计报告讲解视频) 1.主要功能:2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接资料下载链接(可点击): 🌟51单片…...
怎样学好java
最近在看一本java方面的书。《java从入门到精通》,里面看到一段如何学习java的话,觉得非常好,下面我分享一下。 如何学好java语言,是所有初学者都需要面对的问题。其实,每种语言的学习方法都大同小异。初学者需要注意…...
HarmonyOS 数据管理与应用数据持久化(二)
通过键值型数据库实现数据持久化 场景介绍 键值型数据库存储键值对形式的数据,当需要存储的数据没有复杂的关系模型,比如存储商品名称及对应价格、员工工号及今日是否已出勤等,由于数据复杂度低,更容易兼容不同数据库版本和设备…...
Hadoop环境搭建及Demo
参考博客 Windows 10安装Hadoop 3.3.0教程 (kontext.tech) Hadoop入门篇——伪分布模式安装 & WordCount词频统计 | Liu Baoshuai’s Blog Hadoop安装教程 Linux版_linux和hadoop的安装_lnlnldczxy的博客-CSDN博客 hadoop启动出错 The value of property bind.address …...
更新一下数据集
UCI Machine Learning Repository UCI的数据集还是挺老牌的,最近换了地址,我就再记录一下。 左边是比较常见的数据集,比如Iris很经典,Heart Disease这也是,包括Wine,通常对于初学者学习比较好,…...
web3之跨链预言机SupraOracles:什么是Supra
文章目录 web3之跨链预言机SupraOracles什么是Supra什么是DORA(分布式Oracle协议)使用场景web3之跨链预言机SupraOracles 什么是Supra 官网:https://supraoracles.com/ 预言机的核心价值就在于数据传输,数据传输的速度、准确性、安全性更是重中之重。Supra Oracles 就是这…...
关系型数据库 期末复习(未完
关系型数据库 绪论概念间的关系数据库的历史信息和数据数据模型 关系模型数据结构关系完整性关系操作语言 关系代数语言 绪论 概念间的关系 数据->数据库->数据库管理系统->数据库系统 数据库的历史 人工管理阶段 -> 文件系统阶段 -> 数据库系统阶段 数据库…...
【学习笔记】CF1895G Two Characters, Two Colors
感谢grass8sheep提供的思路。 首先,我们可以用 D P DP DP解决这个问题。 设 f i , j f_{i,j} fi,j表示前 i i i个数中有 j j j个为 1 1 1的位置为红色的最大价值。则转移如下: f i , j ← f i − 1 , j b i f_{i,j}\gets f_{i-1,j}b_i fi,j←fi−…...
GZ035 5G组网与运维赛题第10套
2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项(高职组) 赛题第10套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通(35分) 子任务1:5G公共网络部署与调试(15分) 子…...
基于SSM的教学管理系统(有报告)。Javaee项目。
演示视频: 基于SSM的教学管理系统(有报告)。Javaee项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring SpringMvc My…...
软件测试工作流程
流程体系介绍 在以往的项目工作中,我参与过,需求评审、测试计划制定、测试用例编写、测试用例执行、测试脚本编写、测试脚本的执行,进行回归测试、验收测试、编写阶段性测试报告等工作 需求分析,需求评审(RPD、产品原…...
高级文本编辑软件 UltraEdit mac中文版介绍说明
UltraEdit mac是一款在Windows系统中非常出名的文本编辑器, UltraEdit for mac对于IT程序猿来说,更是必不可少,可以使用UltraEdit编辑配置文件、查看16进制文件、代码高亮显示等,虽然Mac上已经有了很多优秀的文本编辑器࿰…...
python模块的介绍和导入
python模块的介绍和导入 概念 在Python中,每个Python代码文件都是一个模块。写程序时,我们可以将代码分散在不同的模块(文件)中,然后在一个模块中引用另一个模块的内容。 导入格式 1、在一个模块中引用(导入)另一个模块可以使用import语句…...
基于单片机的智能饮水机系统
收藏和点赞,您的关注是我创作的动力 文章目录 概要 一、系统设计方案分析2.1 设计功能及性能分析2.2设计方案分析 二、系统的硬件设计3.1 系统设计框图系统软件设计4.1 总体介绍原理图 四、 结论 概要 现在很多学校以及家庭使用的饮水机的功能都是比较单一的&#…...
CSS画圆以及CSS实现动态圆
CSS画圆以及CSS实现动态圆 1. 先看基础(静态圆)1.1 效果如下:1.2 代码如下: 2. 动态圆2.1 一个动态圆2.1.1 让圆渐变2.1.2 圆渐变8秒后消失2.1.3 转动的圆(单个圆) 2.2 多个动态圆 1. 先看基础(…...
K8S知识点(一)
(1)应用部署方式转变 (2)K8S介绍 容器部署容易出现编排问题,为了解决就出现了大量的编排软件,这里将的是K8S编排问题的解决佼佼者 弹性伸缩:当流量从1000变为1200可以,自动开启一个…...
人工智能师求职面试笔试题及答案汇总
人工智能师求职面试笔试题及答案汇总 1.如何在Python中实现一个生成器? 答:在Python中,生成器是一种特殊类型的迭代器。生成器允许你在需要时才生成值,从而节省内存。生成器函数在Python中是通过关键字yield来实现的。例如&…...
【Windows-软件-FFmpeg】(01)通过CMD运行FFmpeg进行操作,快速上手
前言 通过"cmd"运行"ffmpeg"进行操作,快速上手; 实操 【实操一】 说明 使用"ffmpeg"来合并音频文件和视频文件 ; 环境 Windows 11 专业版(22621.2428); 代码 …...
科学/技术路线之争、天才 vs 体制、创新 vs 实用的对立故事
文章目录一、最像「交流电 vs 直流电」的路线大战1. **尼古拉特斯拉 vs 托马斯爱迪生**(你已知的原型)二、同级别的「史诗级科学互怼」2. **伽利略 vs 教会/亚里士多德学派**3. **牛顿 vs 莱布尼茨**4. **爱因斯坦 vs 玻尔**5. **巴斯德 vs 普歇**三、技…...
Windows安卓应用安装神器:APK Installer终极指南
Windows安卓应用安装神器:APK Installer终极指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 想在Windows电脑上直接运行安卓应用吗?厌倦了臃…...
算法工程师的随身匕首:PyTorch 极简入门与实战
PyTorch 快速入门指南 一、PyTorch 是什么? PyTorch 是一个基于 Python 的深度学习框架,由 Facebook AI Research 开发。它以动态计算图和直观的接口著称,是研究和生产中最受欢迎的框架之一。 二、环境安装 # 基础安装(CPU版本&am…...
PySimpleGUI实战:从零构建Python桌面应用界面
1. 为什么选择PySimpleGUI开发桌面应用 第一次接触Python GUI开发时,我被各种框架的选择难住了。Tkinter太原始,PyQt学习曲线陡峭,wxPython文档晦涩难懂。直到发现PySimpleGUI,这个号称"让GUI开发像写Python脚本一样简单&quo…...
Qwen3-Reranker-0.6B与卷积神经网络的结合应用研究
Qwen3-Reranker-0.6B与卷积神经网络的结合应用研究 1. 引言 在信息检索和文档排序领域,如何快速准确地找到最相关的内容一直是个技术难题。传统的检索系统往往只能找到表面相关的文档,而无法深入理解查询和文档之间的语义关联。阿里通义实验室推出的Qw…...
Blazor应用体积爆炸?2026官方推荐的Razor源码生成器配置模板(.NET SDK 9.0.200+实测包体直降63%)
第一章:Blazor应用体积爆炸?2026官方推荐的Razor源码生成器配置模板(.NET SDK 9.0.200实测包体直降63%)Blazor WebAssembly 应用在 .NET SDK 9.0.200 及以上版本中,正式启用基于 Roslyn Source Generators 的 Razor 编…...
突破硬件限制的开源游戏串流方案:Sunshine跨设备游戏体验指南
突破硬件限制的开源游戏串流方案:Sunshine跨设备游戏体验指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 当你拥有一台高性能游戏PC,却只能在固定位置享…...
锂电池主动均衡simulink仿真:基于buckboost拓扑的四节电池均衡技术与各种均衡器的...
锂电池主动均衡simulink仿真 四节电池 基于buckboost(升降压)拓扑 (还有传统电感均衡开关电容均衡双向反激均衡双层准谐振均衡环形均衡器cuk耦合电感)被动均衡电阻式均衡 、分层架构式均衡以及分层式电路均衡,多层次电路,充放电。…...
.NET 11原生AI推理引擎深度评测:实测TensorRT/ONNX Runtime/ML.NET在x64与ARM64服务器上提速3.8倍的关键配置
第一章:.NET 11原生AI推理引擎的演进与企业级定位.NET 11标志着微软在统一AI与传统企业开发范式上的关键跃迁——其内置的原生AI推理引擎(Native AI Inference Engine)不再依赖外部Python运行时或模型服务桥接层,而是深度集成于Co…...
Krita智能选区插件:AI驱动的图像分割解决方案
Krita智能选区插件:AI驱动的图像分割解决方案 【免费下载链接】krita-vision-tools Krita plugin which adds selection tools to mask objects with a single click, or by drawing a bounding box. 项目地址: https://gitcode.com/gh_mirrors/kr/krita-vision-t…...
