QCoreApplication::requestPermission: streamline the implementation
Having a context object is the common case, so it's worth optimizing for it. Remove the routing through a metacall event, which isn't needed, in favor of a simple queued invokeMethod. Also, always provide a context object when calling the slot, even if one wasn't provided by the user; simply use the "sender" object, that is, the internal QObject that is activating the slot. (This way we match the semantics context-less connect() overload, which uses the sender object as a context.) Change-Id: I72051fc48cbda5729145557f15cec4693ffde6ce Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
6add599079
commit
0bd1fc0060
@ -2884,57 +2884,41 @@ Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permis
|
|||||||
void QCoreApplication::requestPermission(const QPermission &requestedPermission,
|
void QCoreApplication::requestPermission(const QPermission &requestedPermission,
|
||||||
QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context)
|
QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context)
|
||||||
{
|
{
|
||||||
QtPrivate::SlotObjSharedPtr slotObj(QtPrivate::SlotObjUniquePtr{slotObjRaw}); // adopts
|
QtPrivate::SlotObjUniquePtr slotObj{slotObjRaw}; // adopts
|
||||||
|
Q_ASSERT(slotObj);
|
||||||
|
|
||||||
if (QThread::currentThread() != QCoreApplicationPrivate::mainThread()) {
|
if (QThread::currentThread() != QCoreApplicationPrivate::mainThread()) {
|
||||||
qWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
|
qWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(slotObj);
|
|
||||||
|
|
||||||
// Used as the signalID in the metacall event and only used to
|
|
||||||
// verify that we are not processing an unrelated event, not to
|
|
||||||
// emit the right signal. So using a value that can never clash
|
|
||||||
// with any signal index. Clang doesn't like this to be a static
|
|
||||||
// member of the PermissionReceiver.
|
|
||||||
static constexpr ushort PermissionReceivedID = 0xffff;
|
|
||||||
|
|
||||||
// If we have a context object, then we dispatch the permission response
|
|
||||||
// asynchronously through a received object that lives in the same thread
|
|
||||||
// as the context object. Otherwise we call the functor synchronously when
|
|
||||||
// we get a response (which might still be asynchronous for the caller).
|
|
||||||
class PermissionReceiver : public QObject
|
class PermissionReceiver : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PermissionReceiver(const QtPrivate::SlotObjSharedPtr &slotObject, const QObject *context)
|
explicit PermissionReceiver(QtPrivate::SlotObjUniquePtr &&slotObject, const QObject *context)
|
||||||
: slotObject(slotObject), context(context)
|
: slotObject(std::move(slotObject)), context(context ? context : this)
|
||||||
{}
|
{
|
||||||
|
Q_ASSERT(this->context);
|
||||||
|
moveToThread(this->context->thread());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
void finalizePermissionRequest(const QPermission &permission)
|
||||||
bool event(QEvent *event) override {
|
{
|
||||||
if (event->type() == QEvent::MetaCall) {
|
|
||||||
auto metaCallEvent = static_cast<QMetaCallEvent *>(event);
|
|
||||||
if (metaCallEvent->id() == PermissionReceivedID) {
|
|
||||||
Q_ASSERT(slotObject);
|
Q_ASSERT(slotObject);
|
||||||
// only execute if context object is still alive
|
// only execute if context object is still alive
|
||||||
if (context)
|
if (context) {
|
||||||
slotObject->call(const_cast<QObject*>(context.data()), metaCallEvent->args());
|
void *args[] = { nullptr, const_cast<QPermission *>(&permission) };
|
||||||
|
slotObject->call(const_cast<QObject *>(context.data()), args);
|
||||||
|
}
|
||||||
deleteLater();
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QObject::event(event);
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
QtPrivate::SlotObjSharedPtr slotObject;
|
QtPrivate::SlotObjSharedPtr slotObject;
|
||||||
QPointer<const QObject> context;
|
QPointer<const QObject> context;
|
||||||
};
|
};
|
||||||
PermissionReceiver *receiver = nullptr;
|
|
||||||
if (context) {
|
PermissionReceiver *receiver = new PermissionReceiver(std::move(slotObj), context);
|
||||||
receiver = new PermissionReceiver(slotObj, context);
|
|
||||||
receiver->moveToThread(context->thread());
|
|
||||||
}
|
|
||||||
|
|
||||||
QPermissions::Private::requestPermission(requestedPermission, [=](Qt::PermissionStatus status) {
|
QPermissions::Private::requestPermission(requestedPermission, [=](Qt::PermissionStatus status) {
|
||||||
Q_ASSERT_X(status != Qt::PermissionStatus::Undetermined, "QPermission",
|
Q_ASSERT_X(status != Qt::PermissionStatus::Undetermined, "QPermission",
|
||||||
@ -2945,15 +2929,10 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission,
|
|||||||
if (QCoreApplication::self) {
|
if (QCoreApplication::self) {
|
||||||
QPermission permission = requestedPermission;
|
QPermission permission = requestedPermission;
|
||||||
permission.m_status = status;
|
permission.m_status = status;
|
||||||
|
QMetaObject::invokeMethod(receiver,
|
||||||
if (receiver) {
|
&PermissionReceiver::finalizePermissionRequest,
|
||||||
auto metaCallEvent = QMetaCallEvent::create(slotObj.get(), qApp,
|
Qt::QueuedConnection,
|
||||||
PermissionReceivedID, permission);
|
permission);
|
||||||
qApp->postEvent(receiver, metaCallEvent);
|
|
||||||
} else {
|
|
||||||
void *argv[] = { nullptr, &permission };
|
|
||||||
slotObj->call(const_cast<QObject*>(context), argv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user