• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

igor-krechetov / hsmcpp / 4957453907

pending completion
4957453907

push

github

igor-krechetov
[0.37.0][r] fix early delete issue

74 of 74 new or added lines in 5 files covered. (100.0%)

2291 of 2482 relevant lines covered (92.3%)

1739.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.96
/src/HsmEventDispatcherQt.cpp
1
// Copyright (C) 2021 Igor Krechetov
2
// Distributed under MIT license. See file LICENSE for details
3

4
#include "hsmcpp/HsmEventDispatcherQt.hpp"
5

6
#include <QAbstractEventDispatcher>
7
#include <QCoreApplication>
8
#include <QThread>
9
#include <QVariant>
10

11
#include "hsmcpp/logging.hpp"
12
#include "hsmcpp/os/CriticalSection.hpp"
13

14
namespace hsmcpp {
15

16
constexpr const char* HSM_TRACE_CLASS = "HsmEventDispatcherQt";
17

18
#define QT_DISPATCH_EVENT (777)
19

20
QEvent::Type HsmEventDispatcherQt::mQtDispatchEventType = QEvent::None;
21

22
HsmEventDispatcherQt::HsmEventDispatcherQt(const size_t eventsCacheSize)
17✔
23
    : HsmEventDispatcherBase(eventsCacheSize)
24
    , QObject(nullptr) {
17✔
25
}
17✔
26

27
HsmEventDispatcherQt::~HsmEventDispatcherQt() {
32✔
28
    HSM_TRACE_CALL_DEBUG();
16✔
29

30
    HsmEventDispatcherQt::stop();
16✔
31
}
32✔
32

33
std::shared_ptr<HsmEventDispatcherQt> HsmEventDispatcherQt::create(const size_t eventsCacheSize) {
17✔
34
    return std::shared_ptr<HsmEventDispatcherQt>(new HsmEventDispatcherQt(eventsCacheSize), &HsmEventDispatcherBase::handleDelete);
34✔
35
}
36

37
bool HsmEventDispatcherQt::deleteSafe() {
17✔
38
    QObject::deleteLater();
17✔
39

40
    return false;
17✔
41
}
42

43
bool HsmEventDispatcherQt::start() {
130✔
44
    HSM_TRACE_CALL_DEBUG();
130✔
45
    bool result = true;
130✔
46

47
    if (QEvent::None == mQtDispatchEventType) {
130✔
48
        int newDispatchEvent = QEvent::registerEventType(static_cast<int>(QEvent::User) + QT_DISPATCH_EVENT);
1✔
49

50
        if (newDispatchEvent > 0) {
1✔
51
            mQtDispatchEventType = static_cast<QEvent::Type>(newDispatchEvent);
1✔
52
        } else {
53
            result = false;
54
        }
55
    }
56

57
    if (true == result) {
1✔
58
        // if dispatcher wasn't created on main thread we need to move it there
59
        if (QObject::thread() != QCoreApplication::eventDispatcher()->thread()) {
130✔
60
            QObject::moveToThread(QCoreApplication::eventDispatcher()->thread());
×
61
        }
62
    }
63

64
    return result;
130✔
65
}
66

67
void HsmEventDispatcherQt::stop() {
34✔
68
    HSM_TRACE_CALL_DEBUG();
34✔
69

70
    HsmEventDispatcherBase::stop();
34✔
71
    unregisterAllTimerHandlers();
34✔
72
    unregisterAllEventHandlers();
34✔
73
}
34✔
74

75
void HsmEventDispatcherQt::emitEvent(const HandlerID_t handlerID) {
456✔
76
    HSM_TRACE_CALL_DEBUG();
456✔
77

78
    if (QEvent::None != mQtDispatchEventType) {
456✔
79
        HsmEventDispatcherBase::emitEvent(handlerID);
456✔
80
    }
81
}
456✔
82

83
void HsmEventDispatcherQt::unregisterAllTimerHandlers() {
34✔
84
    CriticalSection cs(mRunningTimersSync);
34✔
85

86
    for (auto it = mNativeTimerHandlers.begin(); it != mNativeTimerHandlers.end(); ++it) {
35✔
87
        it->second->deleteLater();
1✔
88
    }
89

90
    mNativeTimerHandlers.clear();
34✔
91
}
34✔
92

93
void HsmEventDispatcherQt::startTimerImpl(const TimerID_t timerID, const unsigned int intervalMs, const bool isSingleShot) {
18✔
94
    HSM_TRACE_CALL_DEBUG_ARGS("timerID=%d, intervalMs=%d, isSingleShot=%d",
95
                              SC2INT(timerID),
96
                              intervalMs,
97
                              BOOL2INT(isSingleShot));
18✔
98
    auto it = mNativeTimerHandlers.find(timerID);
18✔
99

100
    if (mNativeTimerHandlers.end() == it) {
18✔
101
        auto funcCreateTimer = [&]() {
36✔
102
            QTimer* newTimer = new QTimer(this);
18✔
103

104
            newTimer->setProperty("hsmid", QVariant(timerID));
18✔
105
            connect(newTimer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
18✔
106
            newTimer->setSingleShot(isSingleShot);
18✔
107
            newTimer->start(intervalMs);
18✔
108

109
            CriticalSection cs(mRunningTimersSync);
18✔
110
            mNativeTimerHandlers.emplace(timerID, newTimer);
18✔
111
        };
18✔
112

113
        // NOTE: need to make sure that QTimer is started only from Qt main thread
114
        QThread* callerThread = QThread::currentThread();
18✔
115

116
        if (qApp->thread() != callerThread) {
18✔
117
            QTimer* mainthreadTimer = new QTimer();
6✔
118

119
            mainthreadTimer->moveToThread(qApp->thread());
6✔
120
            mainthreadTimer->setSingleShot(true);
6✔
121

122
            QObject::connect(mainthreadTimer, &QTimer::timeout, [=]() {
6✔
123
                funcCreateTimer();
6✔
124
                mainthreadTimer->deleteLater();
6✔
125
            });
126
            QMetaObject::invokeMethod(mainthreadTimer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
6✔
127
        } else {
128
            funcCreateTimer();
12✔
129
        }
130
    } else {
131
        HSM_TRACE_ERROR("timer with id=%d already exists", timerID);
18✔
132
    }
133
}
18✔
134

135
void HsmEventDispatcherQt::stopTimerImpl(const TimerID_t timerID) {
8✔
136
    HSM_TRACE_CALL_DEBUG_ARGS("timerID=%d", SC2INT(timerID));
8✔
137
    CriticalSection cs(mRunningTimersSync);
8✔
138
    auto it = mNativeTimerHandlers.find(timerID);
8✔
139

140
    if (mNativeTimerHandlers.end() != it) {
8✔
141
        it->second->deleteLater();
7✔
142
        mNativeTimerHandlers.erase(it);
7✔
143
    }
144
}
8✔
145

146
void HsmEventDispatcherQt::onTimerEvent() {
14✔
147
    QObject* ptrTimer = qobject_cast<QTimer*>(QObject::sender());
14✔
148

149
    if (nullptr != ptrTimer) {
14✔
150
        const TimerID_t timerID = ptrTimer->property("hsmid").toInt();
14✔
151

152
        HSM_TRACE_CALL_DEBUG_ARGS("timerID=%d", SC2INT(timerID));
14✔
153
        const bool restartTimer = handleTimerEvent(timerID);
14✔
154

155
        if (false == restartTimer) {
14✔
156
            CriticalSection cs(mRunningTimersSync);
10✔
157
            auto itTimer = mNativeTimerHandlers.find(timerID);
10✔
158

159
            if (mNativeTimerHandlers.end() != itTimer) {
10✔
160
                itTimer->second->deleteLater();
10✔
161
                mNativeTimerHandlers.erase(itTimer);
10✔
162
            } else {
163
                HSM_TRACE_ERROR("unexpected error. timer not found");
10✔
164
            }
165
        }
10✔
166
    }
167
}
14✔
168

169
void HsmEventDispatcherQt::notifyDispatcherAboutEvent() {
467✔
170
    QCoreApplication::postEvent(this, new QEvent(mQtDispatchEventType));
467✔
171
}
467✔
172

173
void HsmEventDispatcherQt::customEvent(QEvent* ev) {
467✔
174
    HSM_TRACE_CALL_DEBUG();
467✔
175

176
    if ((false == mStopDispatcher) && (ev->type() == mQtDispatchEventType)) {
467✔
177
        HsmEventDispatcherBase::dispatchPendingEvents();
446✔
178
    }
179
}
467✔
180

181
}  // namespace hsmcpp
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc