Commit c4edb77d authored by Alexander A. Maly's avatar Alexander A. Maly

Fixed bug of crashing using Keyboard actor

On MacOS Catalina std::queue does not check for non-emptyness on pop().
It led to size became equal to (uint64_t) (-1) and crash when emptying
the Keyboard events queue because in LockedQueue::dequeue we always popped.
parent d45ee3b7
Pipeline #3444 passed with stages
in 4 minutes and 27 seconds
...@@ -117,15 +117,14 @@ void KeyboardModule::finalizeRun() ...@@ -117,15 +117,14 @@ void KeyboardModule::finalizeRun()
/* public slot */ bool KeyboardModule::runKeyHit() /* public slot */ bool KeyboardModule::runKeyHit()
{ {
/* алг лог клавиша нажата */ /* алг лог клавиша нажата */
const bool result = ! buffer_.empty(); bool result = ! buffer_.empty();
return result; return result;
} }
/* public slot */ int KeyboardModule::runKeyCode() /* public slot */ int KeyboardModule::runKeyCode()
{ {
/* алг цел код клавиши */ /* алг цел код клавиши */
const int result = buffer_.dequeue().kumirCode; int result = buffer_.dequeue().kumirCode;
return result; return result;
} }
......
...@@ -22,9 +22,21 @@ You should change it corresponding to functionality. ...@@ -22,9 +22,21 @@ You should change it corresponding to functionality.
namespace ActorKeyboard namespace ActorKeyboard
{ {
struct KeyEvent {
static const qint64 MAX_DELTA = 10;
int kumirCode;
qint64 timestamp;
explicit KeyEvent(int kumirCode_) : kumirCode(kumirCode_)
{
timestamp = QDateTime::currentMSecsSinceEpoch();
}
explicit KeyEvent(): kumirCode(0), timestamp(0) {}
~KeyEvent() {}
};
class KeyboardModule class KeyboardModule : public KeyboardModuleBase
: public KeyboardModuleBase
{ {
Q_OBJECT Q_OBJECT
public /* methods */: public /* methods */:
...@@ -82,28 +94,12 @@ public slots: ...@@ -82,28 +94,12 @@ public slots:
int runOperatorASTERISK(const int self, const ActorKeyboard::Keycode &other); int runOperatorASTERISK(const int self, const ActorKeyboard::Keycode &other);
protected: protected:
struct KeyEvent {
static const qint64 MAX_DELTA = 10;
int kumirCode;
qint64 timestamp;
inline explicit KeyEvent(int kumirCodee) : kumirCode(kumirCodee)
{
timestamp = QDateTime::currentMSecsSinceEpoch();
}
inline explicit KeyEvent(): kumirCode(0), timestamp(0) {}
};
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event);
static int polyakovCodeOfKey(int qtCode, const QString &text); static int polyakovCodeOfKey(int qtCode, const QString &text);
kumir2::LockedQueue<KeyEvent> buffer_; kumir2::LockedQueue<KeyEvent> buffer_;
KeyEvent lastPressed_; KeyEvent lastPressed_;
QMutex lastPressedLock_; QMutex lastPressedLock_;
}; };
......
...@@ -60,25 +60,28 @@ template <typename T, class Semaphore = QSemaphore, class Mutex = QMutex> ...@@ -60,25 +60,28 @@ template <typename T, class Semaphore = QSemaphore, class Mutex = QMutex>
class LockedQueue class LockedQueue
{ {
public: public:
inline bool empty() const bool empty() const
{ {
mutex_.lock(); mutex_.lock();
const bool result = buffer_.empty(); bool result = buffer_.empty();
mutex_.unlock(); mutex_.unlock();
return result; return result;
} }
inline T dequeue() T dequeue()
{ {
T result = nullitem_;
semaphore_.acquire(); semaphore_.acquire();
mutex_.lock(); mutex_.lock();
const T result = buffer_.empty() ? nullitem_ : buffer_.front(); if (!buffer_.empty()) {
buffer_.pop(); result = buffer_.front();
buffer_.pop();
}
mutex_.unlock(); mutex_.unlock();
return result; return result;
} }
inline void enqueue(const T &item) void enqueue(const T &item)
{ {
mutex_.lock(); mutex_.lock();
buffer_.push(item); buffer_.push(item);
...@@ -86,23 +89,17 @@ public: ...@@ -86,23 +89,17 @@ public:
semaphore_.release(); semaphore_.release();
} }
// for STL iterators compatibility void reset(const T &nullitem)
inline void push_back(const T &item)
{
enqueue(item);
}
inline void reset(const T &nullitem)
{ {
mutex_.lock(); mutex_.lock();
nullitem_ = nullitem; nullitem_ = nullitem;
mutex_.unlock(); mutex_.unlock();
while (! static_cast<bool>(semaphore_.available())) { while (! semaphore_.available()) {
semaphore_.release(); semaphore_.release();
} }
} }
inline void clear() void clear()
{ {
mutex_.lock(); mutex_.lock();
while (! buffer_.empty()) { while (! buffer_.empty()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment