当前位置: 首页 > news >正文

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宏&#xff0c; 引发的基于线程安全的Qt 单例模式的使用。 Q_GLOBAL_STATIC /***************************************************************************…...

[批处理]_[初级]_[如何删除变量值里的双引号]

场景 在使用Visual Studio开发本地程序的时&#xff0c;需要在项目属性&#xff0c;生成事件->生成后事件里增加一些资源的打包&#xff0c;复制&#xff0c;删除等操作&#xff0c;那么就需要用到批处理来进行。而传递带空格的路径给外部的批处理文件时就需要双引号引用从…...

51单片机电子钟闹钟温度LCD1602液晶显示设计( proteus仿真+程序+原理图+设计报告+讲解视频)

51单片机电子钟闹钟温度液晶显示设计( proteus仿真程序原理图设计报告讲解视频&#xff09; 1.主要功能&#xff1a;2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接资料下载链接&#xff08;可点击&#xff09;&#xff1a; &#x1f31f;51单片…...

怎样学好java

最近在看一本java方面的书。《java从入门到精通》&#xff0c;里面看到一段如何学习java的话&#xff0c;觉得非常好&#xff0c;下面我分享一下。 如何学好java语言&#xff0c;是所有初学者都需要面对的问题。其实&#xff0c;每种语言的学习方法都大同小异。初学者需要注意…...

HarmonyOS 数据管理与应用数据持久化(二)

通过键值型数据库实现数据持久化 场景介绍 键值型数据库存储键值对形式的数据&#xff0c;当需要存储的数据没有复杂的关系模型&#xff0c;比如存储商品名称及对应价格、员工工号及今日是否已出勤等&#xff0c;由于数据复杂度低&#xff0c;更容易兼容不同数据库版本和设备…...

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的数据集还是挺老牌的&#xff0c;最近换了地址&#xff0c;我就再记录一下。 左边是比较常见的数据集&#xff0c;比如Iris很经典&#xff0c;Heart Disease这也是&#xff0c;包括Wine&#xff0c;通常对于初学者学习比较好&#xff0c;…...

web3之跨链预言机SupraOracles:什么是Supra

文章目录 web3之跨链预言机SupraOracles什么是Supra什么是DORA(分布式Oracle协议)使用场景web3之跨链预言机SupraOracles 什么是Supra 官网:https://supraoracles.com/ 预言机的核心价值就在于数据传输,数据传输的速度、准确性、安全性更是重中之重。Supra Oracles 就是这…...

关系型数据库 期末复习(未完

关系型数据库 绪论概念间的关系数据库的历史信息和数据数据模型 关系模型数据结构关系完整性关系操作语言 关系代数语言 绪论 概念间的关系 数据->数据库->数据库管理系统->数据库系统 数据库的历史 人工管理阶段 -> 文件系统阶段 -> 数据库系统阶段 数据库…...

【学习笔记】CF1895G Two Characters, Two Colors

感谢grass8sheep提供的思路。 首先&#xff0c;我们可以用 D P DP DP解决这个问题。 设 f i , j f_{i,j} fi,j​表示前 i i i个数中有 j j j个为 1 1 1的位置为红色的最大价值。则转移如下&#xff1a; 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组网与运维赛项&#xff08;高职组&#xff09; 赛题第10套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…...

基于SSM的教学管理系统(有报告)。Javaee项目。

演示视频&#xff1a; 基于SSM的教学管理系统&#xff08;有报告&#xff09;。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc My…...

软件测试工作流程

流程体系介绍 在以往的项目工作中&#xff0c;我参与过&#xff0c;需求评审、测试计划制定、测试用例编写、测试用例执行、测试脚本编写、测试脚本的执行&#xff0c;进行回归测试、验收测试、编写阶段性测试报告等工作 需求分析&#xff0c;需求评审&#xff08;RPD、产品原…...

高级文本编辑软件 UltraEdit mac中文版介绍说明

UltraEdit mac是一款在Windows系统中非常出名的文本编辑器&#xff0c; UltraEdit for mac对于IT程序猿来说&#xff0c;更是必不可少&#xff0c;可以使用UltraEdit编辑配置文件、查看16进制文件、代码高亮显示等&#xff0c;虽然Mac上已经有了很多优秀的文本编辑器&#xff0…...

python模块的介绍和导入

python模块的介绍和导入 概念 在Python中&#xff0c;每个Python代码文件都是一个模块。写程序时&#xff0c;我们可以将代码分散在不同的模块(文件)中&#xff0c;然后在一个模块中引用另一个模块的内容。 导入格式 1、在一个模块中引用(导入)另一个模块可以使用import语句…...

基于单片机的智能饮水机系统

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、系统设计方案分析2.1 设计功能及性能分析2.2设计方案分析 二、系统的硬件设计3.1 系统设计框图系统软件设计4.1 总体介绍原理图 四、 结论 概要 现在很多学校以及家庭使用的饮水机的功能都是比较单一的&#…...

CSS画圆以及CSS实现动态圆

CSS画圆以及CSS实现动态圆 1. 先看基础&#xff08;静态圆&#xff09;1.1 效果如下&#xff1a;1.2 代码如下&#xff1a; 2. 动态圆2.1 一个动态圆2.1.1 让圆渐变2.1.2 圆渐变8秒后消失2.1.3 转动的圆&#xff08;单个圆&#xff09; 2.2 多个动态圆 1. 先看基础&#xff08;…...

K8S知识点(一)

&#xff08;1&#xff09;应用部署方式转变 &#xff08;2&#xff09;K8S介绍 容器部署容易出现编排问题&#xff0c;为了解决就出现了大量的编排软件&#xff0c;这里将的是K8S编排问题的解决佼佼者 弹性伸缩&#xff1a;当流量从1000变为1200可以&#xff0c;自动开启一个…...

人工智能师求职面试笔试题及答案汇总

人工智能师求职面试笔试题及答案汇总 1.如何在Python中实现一个生成器&#xff1f; 答&#xff1a;在Python中&#xff0c;生成器是一种特殊类型的迭代器。生成器允许你在需要时才生成值&#xff0c;从而节省内存。生成器函数在Python中是通过关键字yield来实现的。例如&…...

【Windows-软件-FFmpeg】(01)通过CMD运行FFmpeg进行操作,快速上手

前言 通过"cmd"运行"ffmpeg"进行操作&#xff0c;快速上手&#xff1b; 实操 【实操一】 说明 使用"ffmpeg"来合并音频文件和视频文件 &#xff1b; 环境 Windows 11 专业版&#xff08;22621.2428&#xff09;&#xff1b; 代码 &#xf…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...