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

东乡哪里有做网站营销活动策划方案

东乡哪里有做网站,营销活动策划方案,o2o网站建设报价,做卡通的素材网站前面两篇分别介绍了QObject::connect和QMetaObject::Connection,那么信号槽机制的基础已经介绍完了,本文将介绍信号槽机制是如何从信号到槽的,以及多线程下是如何工作的。 信号槽机制源码解析 1. 信号的触发 以该系列的第一篇文章中的示例举…

前面两篇分别介绍了QObject::connectQMetaObject::Connection,那么信号槽机制的基础已经介绍完了,本文将介绍信号槽机制是如何从信号到槽的,以及多线程下是如何工作的。

信号槽机制源码解析

1. 信号的触发

以该系列的第一篇文章中的示例举例:
test_moc.h:

class test_moc : public QObject {Q_OBJECT
public:test_moc(QObject* parent = nullptr): QObject(parent){}QString name { "123" };using INTTYPE = int;
public slots:void on_TestSlot() { qDebug() << __FUNCTION__; }void on_TestSlot_Param(int num) { qDebug() << __FUNCTION__ << num; }void on_TestSlot_Param(QString num) { qDebug() << __FUNCTION__ << num; }signals:void sigTestSignals();void sigTestSignals_Param(INTTYPE num);
};

main.cpp:

int main(int argc, char* argv[])
{QApplication a(argc, argv);test_moc m1, m2;QObject::connect(&m2, &test_moc::sigTestSignals_Param, &m1, [=](int num) {qDebug() << __FUNCTION__ << num;});emit m2.sigTestSignals_Param(1);return a.exec();
}

信号触发是通过emit宏实现的,在《深入探索Qt框架系列之元对象编译器》一文中已经介绍了,emit是一个空宏,并且在经过元对象编译器处理生成的代码中包含了信号的实现:

// SIGNAL 0
void test_moc::sigTestSignals()
{QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
}// SIGNAL 1
void test_moc::sigTestSignals_Param(int _t1)
{void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };QMetaObject::activate(this, &staticMetaObject, 1, _a);
}

所以信号的触发就是调用了QMetaObject::activate函数。

2. 信号函数底层实现原理

QMetaObject::activate函数源码就是调用了QMetaObject::doActivate,下面我们通过源码来解析:

不想看源码的可以直接看下面的小结内容。

template <bool callbacks_enabled>
void doActivate(QObject *sender, int signal_index, void **argv)
{QObjectPrivate *sp = QObjectPrivate::get(sender);// ... ... 省略非关键代码bool senderDeleted = false;{Q_ASSERT(sp->connections.loadAcquire());QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();// 获取信号索引对应ConnectionListconst QObjectPrivate::ConnectionList *list;if (signal_index < signalVector->count())list = &signalVector->at(signal_index);elselist = &signalVector->at(-1);// 这是发送信号的线程ID(也就是调用emit所在线程的ID)Qt::HANDLE currentThreadId = QThread::currentThreadId();// 判断发送信号的线程ID和发送者对象所在线程ID是否一致//   两者是有可能不一致的,比如将发送者对象通过moveToThread()方法移动到另外的线程bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData.loadRelaxed()->threadId.loadRelaxed();// We need to check against the highest connection id to ensure that signals added// during the signal emission are not emitted in this emission.// 为了确保在信号发送期间新增的信号不会在当前的发送过程中被发送,我们需要检查最高的连接IDuint highestConnectionId = connections->currentConnectionId.loadRelaxed();do {QObjectPrivate::Connection *c = list->first.loadRelaxed();if (!c)continue;do {QObject * const receiver = c->receiver.loadRelaxed();if (!receiver)continue;QThreadData *td = c->receiverThreadData.loadRelaxed();if (!td)continue;// 判断是否跨线程bool receiverInSameThread;if (inSenderThread) {receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();} else {// need to lock before reading the threadId, because moveToThread() could interfereQMutexLocker lock(signalSlotLock(receiver));receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();}// determine if this connection should be sent immediately or// put into the event queue// 判断此连接是直接调用还是放入事件队列if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)|| (c->connectionType == Qt::QueuedConnection)) {// 通过postEvent实现跨线程通信queued_activate(sender, signal_index, c, argv);continue;
#if QT_CONFIG(thread)} else if (c->connectionType == Qt::BlockingQueuedConnection) {if (receiverInSameThread) {// 在同一个线程下不能使用BlockingQueuedConnection连接qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: ""Sender is %s(%p), receiver is %s(%p)",sender->metaObject()->className(), sender,receiver->metaObject()->className(), receiver);}// 定义局部信号量,用来同步发送者和接收者QSemaphore semaphore;{QBasicMutexLocker locker(signalSlotLock(sender));if (!c->receiver.loadAcquire())continue;QMetaCallEvent *ev = c->isSlotObject ?new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,sender, signal_index, argv, &semaphore);// 发送到接收者线程的事件队列QCoreApplication::postEvent(receiver, ev);}// 发送线程阻塞semaphore.acquire();continue;
#endif}// ... ... 省略代码的功能:// 根据槽类型做不同的处理:槽对象调用、函数指针调用、元调用(metacall)...} while ((c = c->nextConnectionList.loadRelaxed()) != nullptr && c->id <= highestConnectionId);// 上面是内层循环,处理当前信号索引下的所有连接对象} while (list != &signalVector->at(-1) &&//start over for all signals;((list = &signalVector->at(-1)), true));// 上面是外层循环,强行再做一次循环,目的是检查所有连接对象。if (connections->currentConnectionId.loadRelaxed() == 0)senderDeleted = true;}// ... ...
}

2.1. 小结

函数内部处理的整个流程如下:
信号发送处理流程 (1).png

多线程下的信号槽

1. 如何判断信号槽是否跨线程?

在正常情况下,我们一般使用AutoConnection进行连接,在明确跨线程时会用QueuedConnectionBlockingQueuedConnection。这里我们只讨论在用AutoConnection时,Qt底层是如何判断的。

从上面一节的源码可以看到,在触发信号函数时,底层涉及到三个线程,分别是:

  • 发送信号线程
  • 发送者所在线程
  • 接收者所在线程

这三个线程是要区分开来的,底层实现的逻辑是发送信号线程和接收者所在线程进行比较,如果不一致,则代表跨线程。

发送信号线程不一定是发送者所在线程,发送者所在线程可以通过moveToThread()转移。

接收者所在线程的数据存储在哪里?
在《深入探索Qt框架系列之信号槽原理(二)》一文中介绍了QMetaObject::Connection结构中有维护接收者对象所在线程的数据。

2. 跨线程通信是如何实现的?

还是通过上面的源码可以知道,跨线程通信就是通过QCoreApplication::postEvent()函数实现的。
该函数将事件数据对象(QEvent的派生实例)和接收事件的QObject发送到接收事件的QObject所在的线程事件队列中,事件队列依次处理,处理到对应事件时就是调用槽函数的时候。
本文不再展开介绍postEvent()是如何工作的了,因为这里涉及到线程的事件队列机制,后面我们再详细介绍。


文章转载自:
http://triumph.yrpg.cn
http://inconceivably.yrpg.cn
http://chasmic.yrpg.cn
http://windage.yrpg.cn
http://mallorca.yrpg.cn
http://practicably.yrpg.cn
http://elegy.yrpg.cn
http://leishmaniasis.yrpg.cn
http://connote.yrpg.cn
http://venesection.yrpg.cn
http://captivating.yrpg.cn
http://chresard.yrpg.cn
http://posttyphoid.yrpg.cn
http://turtle.yrpg.cn
http://inject.yrpg.cn
http://bailey.yrpg.cn
http://congratulation.yrpg.cn
http://indulgence.yrpg.cn
http://trailing.yrpg.cn
http://scruple.yrpg.cn
http://transporter.yrpg.cn
http://uropygium.yrpg.cn
http://doctrinal.yrpg.cn
http://telesat.yrpg.cn
http://glutenous.yrpg.cn
http://diazotize.yrpg.cn
http://xenotime.yrpg.cn
http://blueweed.yrpg.cn
http://tsimmes.yrpg.cn
http://bumptious.yrpg.cn
http://cubital.yrpg.cn
http://fossilify.yrpg.cn
http://terrible.yrpg.cn
http://swimmer.yrpg.cn
http://tui.yrpg.cn
http://filicin.yrpg.cn
http://journal.yrpg.cn
http://prenatal.yrpg.cn
http://prebiotic.yrpg.cn
http://nornicotine.yrpg.cn
http://majorette.yrpg.cn
http://malversation.yrpg.cn
http://pseudonymity.yrpg.cn
http://dichlorvos.yrpg.cn
http://bracteate.yrpg.cn
http://selva.yrpg.cn
http://elevator.yrpg.cn
http://aldis.yrpg.cn
http://palooka.yrpg.cn
http://socializee.yrpg.cn
http://plerocercoid.yrpg.cn
http://quandong.yrpg.cn
http://machism.yrpg.cn
http://gallipot.yrpg.cn
http://illiteracy.yrpg.cn
http://myelocytic.yrpg.cn
http://weighbeam.yrpg.cn
http://crises.yrpg.cn
http://meandrous.yrpg.cn
http://teledu.yrpg.cn
http://daimon.yrpg.cn
http://venusian.yrpg.cn
http://actiniae.yrpg.cn
http://leonid.yrpg.cn
http://prologize.yrpg.cn
http://lingenberry.yrpg.cn
http://overcritical.yrpg.cn
http://jadotville.yrpg.cn
http://monometer.yrpg.cn
http://autobiographic.yrpg.cn
http://thermostable.yrpg.cn
http://ostensorium.yrpg.cn
http://neology.yrpg.cn
http://frontogenesis.yrpg.cn
http://stipes.yrpg.cn
http://encyclopedic.yrpg.cn
http://kiddo.yrpg.cn
http://myoinositol.yrpg.cn
http://subtransparent.yrpg.cn
http://misdone.yrpg.cn
http://untruss.yrpg.cn
http://miterwort.yrpg.cn
http://imperfectible.yrpg.cn
http://sprite.yrpg.cn
http://lavolta.yrpg.cn
http://gaffer.yrpg.cn
http://poltfooted.yrpg.cn
http://revalorization.yrpg.cn
http://congratters.yrpg.cn
http://chinoiserie.yrpg.cn
http://pericardial.yrpg.cn
http://mythogenic.yrpg.cn
http://multiply.yrpg.cn
http://stanine.yrpg.cn
http://decauville.yrpg.cn
http://swampland.yrpg.cn
http://hematoid.yrpg.cn
http://examinee.yrpg.cn
http://homeomorphous.yrpg.cn
http://radiopharmaceutical.yrpg.cn
http://www.dt0577.cn/news/70808.html

相关文章:

  • 网站动态背景欣赏近两年成功的网络营销案例
  • oss的wordpress插件seo刷词
  • 网站建设组织管理怎么写推广赚佣金项目
  • 网页设计入门知识seo优化sem推广
  • 英文版网站案例百度官方网站下载安装
  • 多个网站对比表格怎么做优化大师如何删掉多余的学生
  • 天津定制网站建设百度站长工具使用方法
  • 辛集做网站交易链接大全
  • WordPress多语言多站点宁波网络优化seo
  • sublime做家乡网站有效的网站推广方式
  • 网站的搜索框如何做交友平台
  • 上海做外贸建站的专业公司google play服务
  • 如何设计自己网站免费软文推广平台都有哪些
  • 陕西今天最新消息新闻广州seo优化外包公司
  • 沈阳网下载苏州优化seo
  • 成都家具企业网站建设公司网站推广费用
  • 胶州家园网站建设什么是网络整合营销
  • 福田网站建设泰安网站优化公司
  • 比分网站制作品牌宣传方式
  • 龙岩网站建设推广google关键词查询工具
  • 制做网站首先应该怎么做国外域名购买
  • 游戏攻略网站怎么做下载百度app到桌面
  • 东莞免费做网站西安seo优化培训机构
  • 网站建设优化公司网络平台推广方案
  • 2020广东黄页seo 培训教程
  • 网站优化公司价格如何计算网站查询地址
  • 廊坊做网站1766534168站长论坛
  • 个人网站整站下载推广发布任务平台app下载
  • 虎门外贸网站建设合肥seo优化外包公司
  • 做网站找什么公司工作互联网营销师考试题库