summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2023-02-27 13:11:35 +0200
committerAhmad Samir <a.samirh78@gmail.com>2023-07-19 19:40:51 +0300
commit619b03401d54e6334dfd04ead6439134c88ec71b (patch)
tree743d8dcc32424e40a2ebf0c7bb15ab2c019b36a9
parent74422bbf0256861899b73de908b45b1a8c8f1aae (diff)
QTimerInfoList: don't inherit from a container in an exported class
Instead use composition by using a container member; inheriting from containers has a couple of issues: - containers (STL and Qt) don't have virtual destructors, which means that deleting via a pointer to the base-class would be troublesome - as it turns out, inheriting from containers, QList in this case, in an exported derived-class could lead to binary-incompatibility issues (see linked bug report) Drive-by change: - group all private members in one place - make timerInsert() private, nothing should use it from outside the class anyway Change-Id: I69843835d8c854fa4b13e8b4ba3fb69f1484f6a6 Fixes: QTBUG-111959 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm2
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp2
-rw-r--r--src/corelib/kernel/qtimerinfo_unix.cpp45
-rw-r--r--src/corelib/kernel/qtimerinfo_unix_p.h25
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm2
6 files changed, 44 insertions, 34 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index 770cb87e69..b93a38c8a1 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -195,7 +195,7 @@ void QEventDispatcherCoreFoundation::startingUp()
QEventDispatcherCoreFoundation::~QEventDispatcherCoreFoundation()
{
invalidateTimer();
- qDeleteAll(m_timerInfoList);
+ m_timerInfoList.clearTimers();
m_cfSocketNotifier.removeSocketNotifiers();
}
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 58a9dc5e49..1e2777b08b 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -335,7 +335,7 @@ QEventDispatcherGlib::~QEventDispatcherGlib()
Q_D(QEventDispatcherGlib);
// destroy all timer sources
- qDeleteAll(d->timerSource->timerList);
+ d->timerSource->timerList.clearTimers();
d->timerSource->timerList.~QTimerInfoList();
g_source_destroy(&d->timerSource->source);
g_source_unref(&d->timerSource->source);
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index c75b59acfe..d08548e2c4 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -195,7 +195,7 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
{
// cleanup timers
- qDeleteAll(timerList);
+ timerList.clearTimers();
}
void QEventDispatcherUNIXPrivate::setSocketNotifierPending(QSocketNotifier *notifier)
diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp
index 3a823cf53e..eb36478f22 100644
--- a/src/corelib/kernel/qtimerinfo_unix.cpp
+++ b/src/corelib/kernel/qtimerinfo_unix.cpp
@@ -41,9 +41,9 @@ steady_clock::time_point QTimerInfoList::updateCurrentTime()
*/
bool QTimerInfoList::hasPendingTimers()
{
- if (isEmpty())
+ if (timers.isEmpty())
return false;
- return updateCurrentTime() < constFirst()->timeout;
+ return updateCurrentTime() < timers.at(0)->timeout;
}
static bool byTimeout(const QTimerInfo *a, const QTimerInfo *b)
@@ -54,8 +54,8 @@ static bool byTimeout(const QTimerInfo *a, const QTimerInfo *b)
*/
void QTimerInfoList::timerInsert(QTimerInfo *ti)
{
- insert(std::upper_bound(cbegin(), cend(), ti, byTimeout),
- ti);
+ timers.insert(std::upper_bound(timers.cbegin(), timers.cend(), ti, byTimeout),
+ ti);
}
static constexpr milliseconds roundToMillisecond(nanoseconds val)
@@ -236,12 +236,11 @@ bool QTimerInfoList::timerWait(timespec &tm)
auto isWaiting = [](QTimerInfo *tinfo) { return !tinfo->activateRef; };
// Find first waiting timer not already active
- auto it = std::find_if(cbegin(), cend(), isWaiting);
- if (it == cend())
+ auto it = std::find_if(timers.cbegin(), timers.cend(), isWaiting);
+ if (it == timers.cend())
return false;
- QTimerInfo *t = *it;
- nanoseconds timeToWait = t->timeout - now;
+ nanoseconds timeToWait = (*it)->timeout - now;
if (timeToWait > 0ns)
tm = durationToTimespec(roundToMillisecond(timeToWait));
else
@@ -265,7 +264,7 @@ milliseconds QTimerInfoList::remainingDuration(int timerId)
const steady_clock::time_point now = updateCurrentTime();
auto it = findTimerById(timerId);
- if (it == cend()) {
+ if (it == timers.cend()) {
#ifndef QT_NO_DEBUG
qWarning("QTimerInfoList::timerRemainingTime: timer id %i not found", timerId);
#endif
@@ -335,7 +334,7 @@ void QTimerInfoList::registerTimer(int timerId, milliseconds interval,
bool QTimerInfoList::unregisterTimer(int timerId)
{
auto it = findTimerById(timerId);
- if (it == cend())
+ if (it == timers.cend())
return false; // id not found
// set timer inactive
@@ -345,13 +344,13 @@ bool QTimerInfoList::unregisterTimer(int timerId)
if (t->activateRef)
*(t->activateRef) = nullptr;
delete t;
- erase(it);
+ timers.erase(it);
return true;
}
bool QTimerInfoList::unregisterTimers(QObject *object)
{
- if (isEmpty())
+ if (timers.isEmpty())
return false;
auto associatedWith = [this](QObject *o) {
@@ -368,14 +367,14 @@ bool QTimerInfoList::unregisterTimers(QObject *object)
};
};
- qsizetype count = removeIf(associatedWith(object));
+ qsizetype count = timers.removeIf(associatedWith(object));
return count > 0;
}
QList<QAbstractEventDispatcher::TimerInfo> QTimerInfoList::registeredTimers(QObject *object) const
{
QList<QAbstractEventDispatcher::TimerInfo> list;
- for (const QTimerInfo *const t : std::as_const(*this)) {
+ for (const auto &t : timers) {
if (t->obj == object)
list.emplaceBack(t->id, t->interval.count(), t->timerType);
}
@@ -387,7 +386,7 @@ QList<QAbstractEventDispatcher::TimerInfo> QTimerInfoList::registeredTimers(QObj
*/
int QTimerInfoList::activateTimers()
{
- if (qt_disable_lowpriority_timers || isEmpty())
+ if (qt_disable_lowpriority_timers || timers.isEmpty())
return 0; // nothing to do
firstTimerInfo = nullptr;
@@ -397,16 +396,16 @@ int QTimerInfoList::activateTimers()
// Find out how many timer have expired
auto stillActive = [&now](const QTimerInfo *t) { return now < t->timeout; };
// Find first one still active (list is sorted by timeout)
- auto it = std::find_if(cbegin(), cend(), stillActive);
- auto maxCount = it - cbegin();
+ auto it = std::find_if(timers.cbegin(), timers.cend(), stillActive);
+ auto maxCount = it - timers.cbegin();
int n_act = 0;
//fire the timers.
while (maxCount--) {
- if (isEmpty())
+ if (timers.isEmpty())
break;
- QTimerInfo *currentTimerInfo = constFirst();
+ QTimerInfo *currentTimerInfo = timers.constFirst();
if (now < currentTimerInfo->timeout)
break; // no timer has expired
@@ -422,12 +421,12 @@ int QTimerInfoList::activateTimers()
// determine next timeout time
calculateNextTimeout(currentTimerInfo, now);
- if (size() > 1) {
+ if (timers.size() > 1) {
// Find where "currentTimerInfo" should be in the list so as
// to keep the list ordered by timeout
- auto afterCurrentIt = begin() + 1;
- auto iter = std::upper_bound(afterCurrentIt, end(), currentTimerInfo, byTimeout);
- currentTimerInfo = *std::rotate(begin(), afterCurrentIt, iter);
+ auto afterCurrentIt = timers.begin() + 1;
+ auto iter = std::upper_bound(afterCurrentIt, timers.end(), currentTimerInfo, byTimeout);
+ currentTimerInfo = *std::rotate(timers.begin(), afterCurrentIt, iter);
}
if (currentTimerInfo->interval > 0ms)
diff --git a/src/corelib/kernel/qtimerinfo_unix_p.h b/src/corelib/kernel/qtimerinfo_unix_p.h
index 7c23f93c27..0ee81f6967 100644
--- a/src/corelib/kernel/qtimerinfo_unix_p.h
+++ b/src/corelib/kernel/qtimerinfo_unix_p.h
@@ -34,11 +34,8 @@ struct QTimerInfo {
QTimerInfo **activateRef; // - ref from activateTimers
};
-class Q_CORE_EXPORT QTimerInfoList : public QList<QTimerInfo*>
+class Q_CORE_EXPORT QTimerInfoList
{
- // state variables used by activateTimers()
- QTimerInfo *firstTimerInfo = nullptr;
-
public:
QTimerInfoList();
@@ -60,14 +57,28 @@ public:
int activateTimers();
bool hasPendingTimers();
- QList::const_iterator findTimerById(int timerId) const
+ void clearTimers()
{
- auto matchesId = [timerId](const QTimerInfo *t) { return t->id == timerId; };
- return std::find_if(cbegin(), cend(), matchesId);
+ qDeleteAll(timers);
+ timers.clear();
+ }
+
+ bool isEmpty() const { return timers.empty(); }
+
+ qsizetype size() const { return timers.size(); }
+
+ auto findTimerById(int timerId)
+ {
+ auto matchesId = [timerId](const auto &t) { return t->id == timerId; };
+ return std::find_if(timers.cbegin(), timers.cend(), matchesId);
}
private:
std::chrono::steady_clock::time_point updateCurrentTime();
+
+ // state variables used by activateTimers()
+ QTimerInfo *firstTimerInfo = nullptr;
+ QList<QTimerInfo *> timers;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index fd0a4b4717..41caac281b 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -957,7 +957,7 @@ QCocoaEventDispatcher::~QCocoaEventDispatcher()
{
Q_D(QCocoaEventDispatcher);
- qDeleteAll(d->timerInfoList);
+ d->timerInfoList.clearTimers();
d->maybeStopCFRunLoopTimer();
CFRunLoopRemoveSource(mainRunLoop(), d->activateTimersSourceRef, kCFRunLoopCommonModes);
CFRelease(d->activateTimersSourceRef);