diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2019-02-22 15:20:52 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2019-02-22 15:20:52 +0100 |
commit | 7de0f46028e964bd7b7979835ef0a80cf8cb01b7 (patch) | |
tree | 297ad74ff359a0b6975794e37c89764bd5ec5905 /video/video-widget.hpp | |
parent | 388e9e57d8dcc1b5eda16670bae0e4518515504c (diff) |
video/widget: fix mutex starvation
Get rid of contention in `preview_size' and `set_image'.
After switching the Qt mutex to non-recursive, turns out the writer
thread preempts the UI thread to the point of freezing the entire thing.
Mutex fairness is an implementation detail and we must assume unfair
mutexes in the worst case.
Diffstat (limited to 'video/video-widget.hpp')
-rw-r--r-- | video/video-widget.hpp | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/video/video-widget.hpp b/video/video-widget.hpp index 563f468c..ab5d42d2 100644 --- a/video/video-widget.hpp +++ b/video/video-widget.hpp @@ -11,36 +11,39 @@ #include "export.hpp" #include <vector> +#include <atomic> +#include <tuple> #include <QWidget> +#include <QImage> #include <QTimer> + #include <QMutex> -class OTR_VIDEO_EXPORT video_widget : public QWidget +struct OTR_VIDEO_EXPORT video_widget : QWidget { - Q_OBJECT - -public: video_widget(QWidget* parent = nullptr); void update_image(const QImage& image); - void get_preview_size(int& w, int& h); + std::tuple<int, int> preview_size() const; void resizeEvent(QResizeEvent*) override; -protected slots: void paintEvent(QPaintEvent*) override; - void update_and_repaint(); -private: - QTimer timer; + void draw_image(); protected: - QMutex mtx { QMutex::Recursive }; + mutable QMutex mtx { QMutex::NonRecursive }; QImage texture; std::vector<unsigned char> vec; + bool fresh() const; + void set_fresh(bool x); + void set_image(const unsigned char* src, int width, int height, unsigned stride, QImage::Format fmt); - bool freshp = false; +private: + void init_image_nolock(); + QTimer timer; - int W = iround(QWidget::width() * devicePixelRatioF()); - int H = iround(QWidget::height() * devicePixelRatioF()); + std::atomic<QSize> size_ = QSize(320, 240); + std::atomic<bool> fresh_ { false }; - void init_image_nolock(); + static_assert(decltype(fresh_)::is_always_lock_free); }; |