Browse Source

add mode where user inputs are handled by the ticking thread to reduce input delays due to waiting for lock aquiering over multiple frames

Kolja Strohm 1 year ago
parent
commit
72356fc694
4 changed files with 68 additions and 35 deletions
  1. 52 32
      Bildschirm.cpp
  2. 12 3
      Bildschirm.h
  3. 3 0
      Fenster.cpp
  4. 1 0
      Framework.vcxproj

+ 52 - 32
Bildschirm.cpp

@@ -43,7 +43,8 @@ Bildschirm::Bildschirm(WFenster* f)
       tips(new RCArray<ToolTip>()),
       testRend(1),
       fill(1),
-      rend(0)
+      rend(0),
+      handleUserInputsOnTick(0)
 {}
 
 // Destruktor
@@ -61,6 +62,11 @@ Bildschirm::~Bildschirm()
     unlock();
 }
 
+void Bildschirm::setHandleUserInputsOnTick(bool handleOnTick)
+{
+    handleUserInputsOnTick = handleOnTick;
+}
+
 // nicht konstant
 void Bildschirm::lock()
 {
@@ -506,55 +512,69 @@ void Bildschirm3D::tick(double tickval)
     for (Kam3D* k : *kameras)
         rend3D |= k->tick(tickval);
     unlock();
+    if (handleUserInputsOnTick)
+    {
+        queueCs.lock();
+        while (meQueue.getEintragAnzahl() > 0)
+        {
+            MausEreignis me = meQueue.get(0);
+            __super::doMausEreignis(me);
+            for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--)
+                kameras->z(i)->doMausEreignis(me);
+            meQueue.remove(0);
+        }
+        while (teQueue.getEintragAnzahl() > 0)
+        {
+            TastaturEreignis te = teQueue.get(0);
+            __super::doTastaturEreignis(te);
+            for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--)
+                kameras->z(i)->doTastaturEreignis(te);
+            teQueue.remove(0);
+        }
+        queueCs.unlock();
+    }
 }
 
 void Bildschirm3D::doMausEreignis(MausEreignis& me) // sendet maus Ereignis
 {
-    std::unique_lock<std::mutex> lk(mutex);
-    waitingUserInput++;
-    lk.unlock();
-    lock();
-    __super::doMausEreignis(me);
-    for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--)
-        kameras->z(i)->doMausEreignis(me);
-    unlock();
-    lk.lock();
-    waitingUserInput--;
-    if (waitingUserInput == 0)
+    if (handleUserInputsOnTick)
     {
-        lk.unlock();
-        waiting.notify_all();
+        queueCs.lock();
+        meQueue.add(me);
+        queueCs.unlock();
+    }
+    else
+    {
+        lock();
+        __super::doMausEreignis(me);
+        for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--)
+            kameras->z(i)->doMausEreignis(me);
+        unlock();
     }
 }
 
 void Bildschirm3D::doTastaturEreignis(
     TastaturEreignis& te) // sendet tastatur Ereignis
 {
-    std::unique_lock<std::mutex> lk(mutex);
-    waitingUserInput++;
-    lk.unlock();
-    lock();
-    __super::doTastaturEreignis(te);
-    for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--)
-        kameras->z(i)->doTastaturEreignis(te);
-    unlock();
-    lk.lock();
-    waitingUserInput--;
-    if (waitingUserInput == 0)
+    if (handleUserInputsOnTick)
     {
-        lk.unlock();
-        waiting.notify_all();
+        queueCs.lock();
+        teQueue.add(te);
+        queueCs.unlock();
+    }
+    else
+    {
+        lock();
+        __super::doTastaturEreignis(te);
+        for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--)
+            kameras->z(i)->doTastaturEreignis(te);
+        unlock();
     }
 }
 
 void Bildschirm3D::render() // Zeichnet das Bild
 {
-    if (!rend && !rend3D && testRend) return;
-    std::unique_lock<std::mutex> lk(mutex);
-    if (waitingUserInput > 0)
-        waiting.wait(lk);
     rendering = 1;
-    lk.unlock();
     lock();
     renderZeit->messungStart();
     // Clear the back buffer.

+ 12 - 3
Bildschirm.h

@@ -4,6 +4,8 @@
 #include "Array.h"
 #include "Critical.h"
 #include "Punkt.h"
+#include "TastaturEreignis.h"
+#include "MausEreignis.h"
 
 //! DirectX 11 Types
 
@@ -84,9 +86,10 @@ namespace Framework
         bool testRend;
         bool fill;
         bool rend;
-        std::mutex mutex;
-        int waitingUserInput;
-        std::condition_variable waiting;
+        bool handleUserInputsOnTick;
+        Critical queueCs;
+        Array<MausEreignis> meQueue;
+        Array<TastaturEreignis> teQueue;
 
     public:
         //! Konstruktor
@@ -94,6 +97,12 @@ namespace Framework
         DLLEXPORT Bildschirm(WFenster* fenster);
         //! Destruktor
         DLLEXPORT virtual ~Bildschirm();
+        //! if set to true, then maus and keyboard events are added to a queue
+        //! and will be handled at the next call of tick. Otherwise they are
+        //! handled by the calling thread after waiting for a lock between the
+        //! rendering and ticks. This can lead to longer waiting times since the
+        //! lock can not allways be aquired betwean two frames
+        DLLEXPORT void setHandleUserInputsOnTick(bool handleOnTick);
         //! Dies ist notwendig, falls mehrere Threads gleichzeitig den
         //! Bildschirm benutzen. Wenn lock() von zwei threads aufgerufen wird,
         //! wartet der letzte so lange, bis der erste unlock() aufgerufen hat.

+ 3 - 0
Fenster.cpp

@@ -14,6 +14,9 @@
 #ifdef WIN32
 #    include "Maus.h"
 #endif
+#include <iostream>
+
+#include "Zeit.h"
 
 using namespace Framework;
 #ifdef WIN32

+ 1 - 0
Framework.vcxproj

@@ -121,6 +121,7 @@
       <PreprocessorDefinitions>_WIN32;WIN32;_DEBUG;_WINDOWS;_USRDLL;FRAMEWORK_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <BrowseInformation>true</BrowseInformation>
+      <LanguageStandard>stdcpp17</LanguageStandard>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>