From e9bbb68829e972df2e458aa5beec0568d4737f02 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sat, 29 Dec 2018 13:27:21 +0100
Subject: compat/spinlock: implement and use it

---
 compat/check-visible.cpp | 37 +++++++++++++++++++------------------
 compat/check-visible.hpp |  6 +++---
 compat/spinlock.hpp      | 30 ++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 21 deletions(-)
 create mode 100644 compat/spinlock.hpp

(limited to 'compat')

diff --git a/compat/check-visible.cpp b/compat/check-visible.cpp
index 4cdb1b46..d7f24177 100644
--- a/compat/check-visible.cpp
+++ b/compat/check-visible.cpp
@@ -1,31 +1,33 @@
 #include "check-visible.hpp"
 
-#if defined _WIN32
-
+#include "macros.hpp"
 #include "timer.hpp"
-#include "math.hpp"
+#include "spinlock.hpp"
 
-#include <QMutex>
+#include <QWidget>
 #include <QDebug>
 
-#include <windows.h>
-
 constexpr int visible_timeout = 1000;
 constexpr int invisible_timeout = 250;
 
 static Timer timer;
-static QMutex mtx;
+static std::atomic_flag lock = ATOMIC_FLAG_INIT;
 static bool visible = true;
 
+#if defined _WIN32
+
+#include <windows.h>
+
 void set_is_visible(const QWidget& w, bool force)
 {
-    QMutexLocker l(&mtx);
+    spinlock_guard l(lock);
+
+    HWND hwnd = (HWND)w.winId();
 
     if (!force && timer.elapsed_ms() < (visible ? visible_timeout : invisible_timeout))
         return;
 
     timer.start();
-    HWND hwnd = (HWND)w.winId();
 
     if (RECT r; GetWindowRect(hwnd, &r))
     {
@@ -56,22 +58,21 @@ void set_is_visible(const QWidget& w, bool force)
     }
 }
 
-bool check_is_visible()
-{
-    QMutexLocker l(&mtx);
-
-    return visible;
-}
-
 #else
 
 void set_is_visible(const QWidget&, bool)
 {
 }
 
-bool check_is_visible()
+void check_is_visible(bool)
 {
-    return true;
 }
 
 #endif
+
+bool check_is_visible()
+{
+    spinlock_guard l(lock);
+    return visible;
+}
+
diff --git a/compat/check-visible.hpp b/compat/check-visible.hpp
index e24a654b..5b194c7c 100644
--- a/compat/check-visible.hpp
+++ b/compat/check-visible.hpp
@@ -1,12 +1,12 @@
 #pragma once
 
 #include "export.hpp"
-#include "macros.hpp"
+#include "macros1.h"
 
-#include <QWidget>
+class QWidget;
 
 cc_noinline OTR_COMPAT_EXPORT
 void set_is_visible(QWidget const& w, bool force = false);
 
-cc_noinline OTR_COMPAT_EXPORT
+OTR_COMPAT_EXPORT
 bool check_is_visible();
diff --git a/compat/spinlock.hpp b/compat/spinlock.hpp
new file mode 100644
index 00000000..7e4cd8cf
--- /dev/null
+++ b/compat/spinlock.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "macros1.h"
+#include <atomic>
+
+struct spinlock_guard final
+{
+    spinlock_guard(const spinlock_guard&) = delete;
+    spinlock_guard& operator=(const spinlock_guard&) = delete;
+    constexpr spinlock_guard(spinlock_guard&&) noexcept = default;
+
+    cc_forceinline
+    spinlock_guard(std::atomic_flag* lock) noexcept : spinlock_guard(*lock) {}
+
+    cc_forceinline
+    spinlock_guard(std::atomic_flag& lock) noexcept : lock(lock)
+    {
+        while (lock.test_and_set(std::memory_order_acquire))
+            (void)0;
+    }
+
+    cc_forceinline
+    ~spinlock_guard() noexcept
+    {
+        lock.clear(std::memory_order_release);
+    }
+
+private:
+    std::atomic_flag& lock;
+};
-- 
cgit v1.2.3