24#include <QtCore/qalloc.h>
25#include <QtCore/qobject.h>
26#include <QtCore/private/qobject_p.h>
31struct QObjectPrivate::ConnectionList
33 QAtomicPointer<Connection> first;
34 QAtomicPointer<Connection> last;
36static_assert(std::is_trivially_destructible_v<QObjectPrivate::ConnectionList>);
39struct QObjectPrivate::TaggedSignalVector
43 TaggedSignalVector() =
default;
44 TaggedSignalVector(std::nullptr_t)
noexcept : c(0) {}
45 TaggedSignalVector(Connection *v)
noexcept : c(
reinterpret_cast<quintptr>(v)) { Q_ASSERT(v && (
reinterpret_cast<quintptr>(v) & 0x1) == 0); }
46 TaggedSignalVector(SignalVector *v)
noexcept : c(
reinterpret_cast<quintptr>(v) | quintptr(1u)) { Q_ASSERT(v); }
47 explicit operator SignalVector *()
const noexcept
50 return reinterpret_cast<SignalVector *>(c & ~quintptr(1u));
53 explicit operator Connection *()
const noexcept
55 return reinterpret_cast<Connection *>(c);
57 operator uintptr_t()
const noexcept {
return c; }
60struct QObjectPrivate::ConnectionOrSignalVector
64 TaggedSignalVector nextInOrphanList;
69static_assert(std::is_trivially_copyable_v<QObjectPrivate::ConnectionOrSignalVector>);
71struct QObjectPrivate::Connection :
public ConnectionOrSignalVector
76 QAtomicPointer<Connection> nextConnectionList;
77 Connection *prevConnectionList;
80 QAtomicPointer<QObject> receiver;
81 QAtomicPointer<QThreadData> receiverThreadData;
83 StaticMetaCallFunction callFunction;
84 QtPrivate::QSlotObjectBase *slotObj;
86 QAtomicPointer<
const int> argumentTypes;
92 ushort method_relative;
93 signed int signal_index : 27;
94 ushort connectionType : 2;
95 ushort isSlotObject : 1;
96 ushort ownArgumentTypes : 1;
97 ushort isSingleShot : 1;
98 Connection() : ownArgumentTypes(
true) { }
102 Q_ASSERT(!isSlotObject);
103 return method_offset + method_relative;
105 void ref() { ref_.ref(); }
106 void freeSlotObject()
109 slotObj->destroyIfLastRef();
110 isSlotObject =
false;
116 Q_ASSERT(!receiver.loadRelaxed());
117 Q_ASSERT(!isSlotObject);
124struct QObjectPrivate::SignalVector :
public ConnectionOrSignalVector
128 ConnectionList &at(
int i) {
return reinterpret_cast<ConnectionList *>(
this + 1)[i + 1]; }
129 const ConnectionList &at(
int i)
const
131 return reinterpret_cast<
const ConnectionList *>(
this + 1)[i + 1];
133 int count()
const {
return static_cast<
int>(allocated); }
136static_assert(std::is_trivially_copyable_v<QObjectPrivate::SignalVector>);
138struct QObjectPrivate::ConnectionData
142 QAtomicInteger<uint> currentConnectionId;
144 QAtomicPointer<SignalVector> signalVector;
145 Connection *senders =
nullptr;
146 Sender *currentSender =
nullptr;
147 std::atomic<TaggedSignalVector> orphaned = {
nullptr};
151 Q_ASSERT(ref.loadRelaxed() == 0);
152 TaggedSignalVector c = orphaned.exchange(
nullptr, std::memory_order_relaxed);
155 SignalVector *v = signalVector.loadRelaxed();
157 const size_t allocSize =
sizeof(SignalVector) + (v->allocated + 1) *
sizeof(ConnectionList);
159 QtPrivate::sizedFree(v, allocSize);
165 void removeConnection(Connection *c);
171 AlreadyLockedAndTemporarilyReleasingLock
173 void cleanOrphanedConnections(QObject *sender, LockPolicy lockPolicy = NeedToLock)
175 if (orphaned.load(std::memory_order_relaxed) && ref.loadAcquire() == 1)
176 cleanOrphanedConnectionsImpl(sender, lockPolicy);
178 void cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy);
180 ConnectionList &connectionsForSignal(
int signal)
182 return signalVector.loadRelaxed()->at(signal);
185 void resizeSignalVector(size_t size)
187 SignalVector *vector =
this->signalVector.loadRelaxed();
188 if (vector && vector->allocated > size)
190 size = (size + 7) & ~7;
191 void *ptr = QtPrivate::fittedMalloc(
sizeof(SignalVector), &size,
sizeof(ConnectionList), 1);
192 auto newVector =
new (ptr) SignalVector;
199 memcpy(newVector, vector,
200 sizeof(SignalVector) + (vector->allocated + 1) *
sizeof(ConnectionList));
201 start = vector->count();
203 for (
int i = start; i <
int(size); ++i)
204 new (&newVector->at(i)) ConnectionList();
205 newVector->next =
nullptr;
206 newVector->allocated = size;
208 signalVector.storeRelaxed(newVector);
210 TaggedSignalVector o =
nullptr;
212
213
214 o = orphaned.load(std::memory_order_acquire);
216 vector->nextInOrphanList = o;
217 }
while (!orphaned.compare_exchange_strong(o, TaggedSignalVector(vector), std::memory_order_release));
220 int signalVectorCount()
const
222 return signalVector.loadAcquire() ? signalVector.loadRelaxed()->count() : -1;
225 static void deleteOrphaned(TaggedSignalVector o);
228struct QObjectPrivate::Sender
230 Sender(QObject *receiver, QObject *sender,
int signal, ConnectionData *receiverConnections)
231 : receiver(receiver), sender(sender), signal(signal)
233 if (receiverConnections) {
234 previous = receiverConnections->currentSender;
235 receiverConnections->currentSender =
this;
241 receiver->d_func()->connections.loadAcquire()->currentSender = previous;
243 void receiverDeleted()
247 s->receiver =
nullptr;
251 Sender *previous =
nullptr;
Combined button and popup list for selecting options.
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit)
Q_DECLARE_TYPEINFO(QDateTime::Data, Q_RELOCATABLE_TYPE)
#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 Q_DECL_COLD_FUNCTION void connectWarning(const QObject *sender, const QMetaObject *senderMetaObject, const QObject *receiver, const char *message)
static bool check_method_code(int code, const QObject *object, const char *method, const char *func)
static Q_DECL_COLD_FUNCTION void err_info_about_object(const char *func, const QObject *o, ConnectionEnd end)
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_CORE_EXPORT const char * qFlagLocation(const char *method)
SlotObjectGuard()=default