23#include <QtCore/qalloc.h>
24#include <QtCore/qobject.h>
25#include <QtCore/private/qobject_p.h>
30struct QObjectPrivate::ConnectionList
32 QAtomicPointer<Connection> first;
33 QAtomicPointer<Connection> last;
35static_assert(std::is_trivially_destructible_v<QObjectPrivate::ConnectionList>);
38struct QObjectPrivate::TaggedSignalVector
42 TaggedSignalVector() =
default;
43 TaggedSignalVector(std::nullptr_t)
noexcept : c(0) {}
44 TaggedSignalVector(Connection *v)
noexcept : c(
reinterpret_cast<quintptr>(v)) { Q_ASSERT(v && (
reinterpret_cast<quintptr>(v) & 0x1) == 0); }
45 TaggedSignalVector(SignalVector *v)
noexcept : c(
reinterpret_cast<quintptr>(v) | quintptr(1u)) { Q_ASSERT(v); }
46 explicit operator SignalVector *()
const noexcept
49 return reinterpret_cast<SignalVector *>(c & ~quintptr(1u));
52 explicit operator Connection *()
const noexcept
54 return reinterpret_cast<Connection *>(c);
56 operator uintptr_t()
const noexcept {
return c; }
59struct QObjectPrivate::ConnectionOrSignalVector
63 TaggedSignalVector nextInOrphanList;
68static_assert(std::is_trivially_copyable_v<QObjectPrivate::ConnectionOrSignalVector>);
70struct QObjectPrivate::Connection :
public ConnectionOrSignalVector
75 QAtomicPointer<Connection> nextConnectionList;
76 Connection *prevConnectionList;
79 QAtomicPointer<QObject> receiver;
80 QAtomicPointer<QThreadData> receiverThreadData;
82 StaticMetaCallFunction callFunction;
83 QtPrivate::QSlotObjectBase *slotObj;
85 QAtomicPointer<
const int> argumentTypes;
91 ushort method_relative;
92 signed int signal_index : 27;
93 ushort connectionType : 2;
94 ushort isSlotObject : 1;
95 ushort ownArgumentTypes : 1;
96 ushort isSingleShot : 1;
97 Connection() : ownArgumentTypes(
true) { }
101 Q_ASSERT(!isSlotObject);
102 return method_offset + method_relative;
104 void ref() { ref_.ref(); }
105 void freeSlotObject()
108 slotObj->destroyIfLastRef();
109 isSlotObject =
false;
115 Q_ASSERT(!receiver.loadRelaxed());
116 Q_ASSERT(!isSlotObject);
123struct QObjectPrivate::SignalVector :
public ConnectionOrSignalVector
127 ConnectionList &at(
int i) {
return reinterpret_cast<ConnectionList *>(
this + 1)[i + 1]; }
128 const ConnectionList &at(
int i)
const
130 return reinterpret_cast<
const ConnectionList *>(
this + 1)[i + 1];
132 int count()
const {
return static_cast<
int>(allocated); }
135static_assert(std::is_trivially_copyable_v<QObjectPrivate::SignalVector>);
137struct QObjectPrivate::ConnectionData
141 QAtomicInteger<uint> currentConnectionId;
143 QAtomicPointer<SignalVector> signalVector;
144 Connection *senders =
nullptr;
145 Sender *currentSender =
nullptr;
146 std::atomic<TaggedSignalVector> orphaned = {
nullptr};
150 Q_ASSERT(ref.loadRelaxed() == 0);
151 TaggedSignalVector c = orphaned.exchange(
nullptr, std::memory_order_relaxed);
154 SignalVector *v = signalVector.loadRelaxed();
156 const size_t allocSize =
sizeof(SignalVector) + (v->allocated + 1) *
sizeof(ConnectionList);
158 QtPrivate::sizedFree(v, allocSize);
164 void removeConnection(Connection *c);
170 AlreadyLockedAndTemporarilyReleasingLock
172 void cleanOrphanedConnections(QObject *sender, LockPolicy lockPolicy = NeedToLock)
174 if (orphaned.load(std::memory_order_relaxed) && ref.loadAcquire() == 1)
175 cleanOrphanedConnectionsImpl(sender, lockPolicy);
177 void cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy);
179 ConnectionList &connectionsForSignal(
int signal)
181 return signalVector.loadRelaxed()->at(signal);
184 void resizeSignalVector(size_t size)
186 SignalVector *vector =
this->signalVector.loadRelaxed();
187 if (vector && vector->allocated > size)
189 size = (size + 7) & ~7;
190 void *ptr = QtPrivate::fittedMalloc(
sizeof(SignalVector), &size,
sizeof(ConnectionList), 1);
191 auto newVector =
new (ptr) SignalVector;
198 memcpy(newVector, vector,
199 sizeof(SignalVector) + (vector->allocated + 1) *
sizeof(ConnectionList));
200 start = vector->count();
202 for (
int i = start; i <
int(size); ++i)
203 new (&newVector->at(i)) ConnectionList();
204 newVector->next =
nullptr;
205 newVector->allocated = size;
207 signalVector.storeRelaxed(newVector);
209 TaggedSignalVector o =
nullptr;
211
212
213 o = orphaned.load(std::memory_order_acquire);
215 vector->nextInOrphanList = o;
216 }
while (!orphaned.compare_exchange_strong(o, TaggedSignalVector(vector), std::memory_order_release));
219 int signalVectorCount()
const
221 return signalVector.loadAcquire() ? signalVector.loadRelaxed()->count() : -1;
224 static void deleteOrphaned(TaggedSignalVector o);
227struct QObjectPrivate::Sender
229 Sender(QObject *receiver, QObject *sender,
int signal, ConnectionData *receiverConnections)
230 : receiver(receiver), sender(sender), signal(signal)
232 if (receiverConnections) {
233 previous = receiverConnections->currentSender;
234 receiverConnections->currentSender =
this;
240 receiver->d_func()->connections.loadAcquire()->currentSender = previous;
242 void receiverDeleted()
246 s->receiver =
nullptr;
250 Sender *previous =
nullptr;
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)
static void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal, const QMetaObject *receiver, const QMetaMethod &method)
static int * queuedConnectionTypes(QSpan< const QArgumentType > argumentTypes)
static int DIRECT_CONNECTION_ONLY
static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
QObject * qt_qFindChild_helper(const QObject *parent, QAnyStringView name, const QMetaObject &mo, Qt::FindChildOptions options)
static const char * extract_location(const char *member)
Q_TRACE_POINT(qtcore, QMetaObject_activate_slot_functor_entry, void *slotObject)
static bool check_parent_thread(QObject *parent, QThreadData *parentThreadData, QThreadData *currentThreadData)
static int * queuedConnectionTypes(const QMetaMethod &method)
static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
static QBasicMutex * signalSlotLock(const QObject *o)
static Q_DECL_COLD_FUNCTION void err_method_notfound(const QObject *object, const char *method, const char *func)
static bool check_method_code(int code, const QObject *object, const char *method, const char *func)
void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
static bool matches_objectName_non_null(QObject *obj, QAnyStringView name)
Q_TRACE_POINT(qtcore, QObject_dtor, QObject *object)
Q_TRACE_POINT(qtcore, QMetaObject_activate_entry, QObject *sender, int signalIndex)
static int extract_code(const char *member)
static bool check_signal_macro(const QObject *sender, const char *signal, const char *func, const char *op)
static Q_DECL_COLD_FUNCTION void err_info_about_objects(const char *func, const QObject *sender, const QObject *receiver)
Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, QAnyStringView name, const QMetaObject &mo, QList< void * > *list, Qt::FindChildOptions options)
Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_RELOCATABLE_TYPE)
Q_CORE_EXPORT const char * qFlagLocation(const char *method)
SlotObjectGuard()=default