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

igor-krechetov / hsmcpp / 4509400661

pending completion
4509400661

push

github

igor-krechetov
[0.33.0][r] improvement to timers API

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

1921 of 2338 relevant lines covered (82.16%)

161238.04 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
#undef HSM_TRACE_CLASS
17
#define HSM_TRACE_CLASS "HsmEventDispatcherQt"
18

19
#define QT_DISPATCH_EVENT (777)
20

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

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

28
HsmEventDispatcherQt::~HsmEventDispatcherQt() {
30✔
29
    HSM_TRACE_CALL_DEBUG();
15✔
30

31
    HsmEventDispatcherQt::stop();
15✔
32
}
30✔
33

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

38
bool HsmEventDispatcherQt::deleteSafe() {
16✔
39
    QObject::deleteLater();
16✔
40

41
    return false;
16✔
42
}
43

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

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

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

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

65
    return result;
211✔
66
}
67

68
void HsmEventDispatcherQt::stop() {
32✔
69
    HSM_TRACE_CALL_DEBUG();
32✔
70

71
    HsmEventDispatcherBase::stop();
32✔
72
    unregisterAllTimerHandlers();
32✔
73
    unregisterAllEventHandlers();
32✔
74
}
32✔
75

76
void HsmEventDispatcherQt::emitEvent(const HandlerID_t handlerID) {
198,860✔
77
    HSM_TRACE_CALL_DEBUG();
198,860✔
78

79
    if (QEvent::None != mQtDispatchEventType) {
198,860✔
80
        HsmEventDispatcherBase::emitEvent(handlerID);
198,918✔
81
    }
82
}
200,296✔
83

84
void HsmEventDispatcherQt::unregisterAllTimerHandlers() {
32✔
85
    CriticalSection cs(mRunningTimersSync);
32✔
86

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

91
    mNativeTimerHandlers.clear();
32✔
92
}
32✔
93

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

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

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

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

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

117
        if (qApp->thread() != callerThread) {
17✔
118
            QTimer* mainthreadTimer = new QTimer();
5✔
119

120
            mainthreadTimer->moveToThread(qApp->thread());
5✔
121
            mainthreadTimer->setSingleShot(true);
5✔
122

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

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

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

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

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

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

156
        if (false == restartTimer) {
13✔
157
            CriticalSection cs(mRunningTimersSync);
9✔
158
            auto itTimer = mNativeTimerHandlers.find(timerID);
9✔
159

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

170
void HsmEventDispatcherQt::notifyDispatcherAboutEvent() {
200,381✔
171
    QCoreApplication::postEvent(this, new QEvent(mQtDispatchEventType));
200,381✔
172
}
200,385✔
173

174
void HsmEventDispatcherQt::customEvent(QEvent* ev) {
200,412✔
175
    HSM_TRACE_CALL_DEBUG();
200,412✔
176

177
    if ((false == mStopDispatcher) && (ev->type() == mQtDispatchEventType)) {
200,412✔
178
        HsmEventDispatcherBase::dispatchPendingEvents();
200,391✔
179
    }
180
}
200,412✔
181

182
}  // 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