summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qobject_p.h
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-04-05 11:21:04 -0700
committerThiago Macieira <thiago.macieira@intel.com>2022-04-13 20:17:27 -0700
commit06c2478762fafd16190259975bf381f14ad410e9 (patch)
treecc6a56accbc02c74769deb3ee74ce593d2a54c0b /src/corelib/kernel/qobject_p.h
parentd1e9cab81ca94f450b1391822091ed81fec60c92 (diff)
QObjectPrivate: deinline a bunch of stuff only used in QtCore
All of this connection management code is used only in QtCore and mustn't be touched by other modules (not even qtdeclarative). So there's no reason for it to be around and slow down the compilation time of everything using QObjectPrivate. Change-Id: If2e0f4b2190341ebaa31fffd16e31313f1b7020f Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src/corelib/kernel/qobject_p.h')
-rw-r--r--src/corelib/kernel/qobject_p.h221
1 files changed, 5 insertions, 216 deletions
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 4fcd2281e7..ed32a90497 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -135,123 +135,11 @@ public:
typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
struct Connection;
+ struct ConnectionData;
+ struct ConnectionList;
+ struct ConnectionOrSignalVector;
struct SignalVector;
-
- struct ConnectionOrSignalVector {
- union {
- // linked list of orphaned connections that need cleaning up
- ConnectionOrSignalVector *nextInOrphanList;
- // linked list of connections connected to slots in this object
- Connection *next;
- };
-
- static SignalVector *asSignalVector(ConnectionOrSignalVector *c)
- {
- if (reinterpret_cast<quintptr>(c) & 1)
- return reinterpret_cast<SignalVector *>(reinterpret_cast<quintptr>(c) & ~quintptr(1u));
- return nullptr;
- }
- static Connection *fromSignalVector(SignalVector *v) {
- return reinterpret_cast<Connection *>(reinterpret_cast<quintptr>(v) | quintptr(1u));
- }
- };
-
- struct Connection : public ConnectionOrSignalVector
- {
- // linked list of connections connected to slots in this object, next is in base class
- Connection **prev;
- // linked list of connections connected to signals in this object
- QAtomicPointer<Connection> nextConnectionList;
- Connection *prevConnectionList;
-
- QObject *sender;
- QAtomicPointer<QObject> receiver;
- QAtomicPointer<QThreadData> receiverThreadData;
- union {
- StaticMetaCallFunction callFunction;
- QtPrivate::QSlotObjectBase *slotObj;
- };
- QAtomicPointer<const int> argumentTypes;
- QAtomicInt ref_;
- uint id = 0;
- ushort method_offset;
- ushort method_relative;
- signed int signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
- ushort connectionType : 2; // 0 == auto, 1 == direct, 2 == queued, 3 == blocking
- ushort isSlotObject : 1;
- ushort ownArgumentTypes : 1;
- ushort isSingleShot : 1;
- Connection() : ref_(2), ownArgumentTypes(true) {
- //ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
- }
- ~Connection();
- int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; }
- void ref() { ref_.ref(); }
- void freeSlotObject()
- {
- if (isSlotObject) {
- slotObj->destroyIfLastRef();
- isSlotObject = false;
- }
- }
- void deref()
- {
- if (!ref_.deref()) {
- Q_ASSERT(!receiver.loadRelaxed());
- Q_ASSERT(!isSlotObject);
- delete this;
- }
- }
- };
- // ConnectionList is a singly-linked list
- struct ConnectionList {
- QAtomicPointer<Connection> first;
- QAtomicPointer<Connection> last;
- };
-
- struct Sender
- {
- Sender(QObject *receiver, QObject *sender, int signal)
- : receiver(receiver), sender(sender), signal(signal)
- {
- if (receiver) {
- ConnectionData *cd = receiver->d_func()->connections.loadRelaxed();
- previous = cd->currentSender;
- cd->currentSender = this;
- }
- }
- ~Sender()
- {
- if (receiver)
- receiver->d_func()->connections.loadRelaxed()->currentSender = previous;
- }
- void receiverDeleted()
- {
- Sender *s = this;
- while (s) {
- s->receiver = nullptr;
- s = s->previous;
- }
- }
- Sender *previous;
- QObject *receiver;
- QObject *sender;
- int signal;
- };
-
- struct SignalVector : public ConnectionOrSignalVector {
- quintptr allocated;
- // ConnectionList signals[]
- ConnectionList &at(int i)
- {
- return reinterpret_cast<ConnectionList *>(this + 1)[i + 1];
- }
- const ConnectionList &at(int i) const
- {
- return reinterpret_cast<const ConnectionList *>(this + 1)[i + 1];
- }
- int count() const { return static_cast<int>(allocated); }
- };
+ struct Sender;
/*
This contains the all connections from and to an object.
@@ -267,93 +155,6 @@ public:
to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this
linked list.
*/
- struct ConnectionData {
- // the id below is used to avoid activating new connections. When the object gets
- // deleted it's set to 0, so that signal emission stops
- QAtomicInteger<uint> currentConnectionId;
- QAtomicInt ref;
- QAtomicPointer<SignalVector> signalVector;
- Connection *senders = nullptr;
- Sender *currentSender = nullptr; // object currently activating the object
- QAtomicPointer<Connection> orphaned;
-
- ~ConnectionData()
- {
- Q_ASSERT(ref.loadRelaxed() == 0);
- auto *c = orphaned.fetchAndStoreRelaxed(nullptr);
- if (c)
- deleteOrphaned(c);
- SignalVector *v = signalVector.loadRelaxed();
- if (v) {
- v->~SignalVector();
- free(v);
- }
- }
-
- // must be called on the senders connection data
- // assumes the senders and receivers lock are held
- void removeConnection(Connection *c);
- enum LockPolicy {
- NeedToLock,
- // Beware that we need to temporarily release the lock
- // and thus calling code must carefully consider whether
- // invariants still hold.
- AlreadyLockedAndTemporarilyReleasingLock
- };
- void cleanOrphanedConnections(QObject *sender, LockPolicy lockPolicy = NeedToLock)
- {
- if (orphaned.loadRelaxed() && ref.loadAcquire() == 1)
- cleanOrphanedConnectionsImpl(sender, lockPolicy);
- }
- void cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy);
-
- ConnectionList &connectionsForSignal(int signal)
- {
- return signalVector.loadRelaxed()->at(signal);
- }
-
- void resizeSignalVector(uint size)
- {
- SignalVector *vector = this->signalVector.loadRelaxed();
- if (vector && vector->allocated > size)
- return;
- size = (size + 7) & ~7;
- void *ptr = malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList));
- auto newVector = new (ptr) SignalVector;
-
- int start = -1;
- if (vector) {
- // not (yet) existing trait:
- //static_assert(std::is_relocatable_v<SignalVector>);
- //static_assert(std::is_relocatable_v<ConnectionList>);
- memcpy(newVector, vector, sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList));
- start = vector->count();
- }
- for (int i = start; i < int(size); ++i)
- new (&newVector->at(i)) ConnectionList();
- newVector->next = nullptr;
- newVector->allocated = size;
-
- signalVector.storeRelaxed(newVector);
- if (vector) {
- Connection *o = nullptr;
- /* No ABA issue here: When adding a node, we only care about the list head, it doesn't
- * matter if the tail changes.
- */
- do {
- o = orphaned.loadRelaxed();
- vector->nextInOrphanList = o;
- } while (!orphaned.testAndSetRelease(o, ConnectionOrSignalVector::fromSignalVector(vector)));
-
- }
- }
- int signalVectorCount() const
- {
- return signalVector.loadAcquire() ? signalVector.loadRelaxed()->count() : -1;
- }
-
- static void deleteOrphaned(ConnectionOrSignalVector *c);
- };
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
@@ -412,14 +213,7 @@ public:
void **slot);
static bool disconnect(Connection *c);
- void ensureConnectionData()
- {
- if (connections.loadRelaxed())
- return;
- ConnectionData *cd = new ConnectionData;
- cd->ref.ref();
- connections.storeRelaxed(cd);
- }
+ void ensureConnectionData();
virtual std::string flagsForDumping() const;
@@ -445,8 +239,6 @@ public:
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};
-Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_RELOCATABLE_TYPE);
-
/*
Catch mixing of incompatible library versions.
@@ -587,9 +379,6 @@ bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1
&SignalType::Object::staticMetaObject);
}
-Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_RELOCATABLE_TYPE);
-
class QSemaphore;
class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent
{