From a68ddf84441c1076ba7e334c294d2c260cd6a002 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Fri, 4 Jun 2021 19:18:33 +0200
Subject: [PATCH] [#43] Synchronized window events with mutexes

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Event.hpp               | 20 ++++++++++
 include/vkcv/Window.hpp              |  1 +
 projects/first_mesh/src/main.cpp     |  2 -
 projects/first_triangle/src/main.cpp |  2 -
 src/vkcv/Window.cpp                  | 57 +++++++++++++++++-----------
 5 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/include/vkcv/Event.hpp b/include/vkcv/Event.hpp
index 0836e836..dfa1325a 100644
--- a/include/vkcv/Event.hpp
+++ b/include/vkcv/Event.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <functional>
+#include <mutex>
 
 namespace vkcv {
 
@@ -17,6 +18,7 @@ namespace vkcv {
     struct event {
     private:
         std::vector<typename event_function<T...>::type> m_handles;
+        std::mutex m_mutex;
 
     public:
 
@@ -25,9 +27,13 @@ namespace vkcv {
          * @param arguments of the given function
          */
         void operator()(T... arguments) {
+			lock();
+        	
             for (auto &handle : this->m_handles) {
                 handle(arguments...);
             }
+            
+            unlock();
         }
 
         /**
@@ -49,6 +55,20 @@ namespace vkcv {
                     this->m_handles.end()
             );
         }
+        
+        /**
+         * locks the event so its function handles won't be called
+         */
+        void lock() {
+        	m_mutex.lock();
+        }
+	
+		/**
+		* unlocks the event so its function handles can be called after locking
+		*/
+        void unlock() {
+        	m_mutex.unlock();
+        }
 
         event() = default;
 
diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp
index f71671c9..f11a38b7 100644
--- a/include/vkcv/Window.hpp
+++ b/include/vkcv/Window.hpp
@@ -7,6 +7,7 @@
 
 #define NOMINMAX
 #include <algorithm>
+
 #include "Event.hpp"
 
 struct GLFWwindow;
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 01d8b74f..723bc9a5 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -17,8 +17,6 @@ int main(int argc, const char** argv) {
 
 	vkcv::CameraManager cameraManager(window, static_cast<float>(window.getWidth()), static_cast<float>(window.getHeight()));
 
-	window.initEvents();
-
 	vkcv::Core core = vkcv::Core::create(
 		window,
 		applicationName,
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 397498e6..6c3b2272 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -18,8 +18,6 @@ int main(int argc, const char** argv) {
 
 	vkcv::CameraManager cameraManager(window, windowWidth, windowHeight);
 
-	window.initEvents();
-
 	vkcv::Core core = vkcv::Core::create(
 		window,
 		applicationName,
diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp
index c21271b7..210178fa 100644
--- a/src/vkcv/Window.cpp
+++ b/src/vkcv/Window.cpp
@@ -10,55 +10,68 @@
 
 namespace vkcv {
 
-    static uint32_t s_WindowCount = 0;
+	static std::vector<GLFWwindow*> s_Windows;
 
     Window::Window(GLFWwindow *window)
             : m_window(window) {
+		glfwSetWindowUserPointer(m_window, this);
+	
+		// combine Callbacks with Events
+		glfwSetMouseButtonCallback(m_window, Window::onMouseButtonEvent);
+		glfwSetCursorPosCallback(m_window, Window::onMouseMoveEvent);
+		glfwSetWindowSizeCallback(m_window, Window::onResize);
+		glfwSetKeyCallback(m_window, Window::onKeyEvent);
+		glfwSetScrollCallback(m_window, Window::onMouseScrollEvent);
     }
 
     Window::~Window() {
+		s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window));
         glfwDestroyWindow(m_window);
-        s_WindowCount--;
 
-        if(s_WindowCount == 0) {
+        if(s_Windows.empty()) {
             glfwTerminate();
         }
     }
 
     Window Window::create( const char *windowTitle, int width, int height, bool resizable) {
-        if(s_WindowCount == 0) {
+        if(s_Windows.empty()) {
             glfwInit();
         }
-        s_WindowCount++;
 
         width = std::max(width, 1);
         height = std::max(height, 1);
 
         glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
         glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE);
-        GLFWwindow *window;
-        window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr);
+		GLFWwindow *window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr);
+		
+		s_Windows.push_back(window);
 
         return Window(window);
     }
 
-    void Window::initEvents() {
-        glfwSetWindowUserPointer(m_window, this);
-
-        // combine Callbacks with Events
-        glfwSetMouseButtonCallback(m_window, Window::onMouseButtonEvent);
-
-        glfwSetCursorPosCallback(m_window, Window::onMouseMoveEvent);
-
-        glfwSetWindowSizeCallback(m_window, Window::onResize);
-
-        glfwSetKeyCallback(m_window, Window::onKeyEvent);
-
-        glfwSetScrollCallback(m_window, Window::onMouseScrollEvent);
-    }
-
     void Window::pollEvents() {
+    	for (auto glfwWindow : s_Windows) {
+			auto window = static_cast<Window *>(glfwGetWindowUserPointer(glfwWindow));
+			
+			window->e_mouseButton.unlock();
+			window->e_mouseMove.unlock();
+			window->e_resize.unlock();
+			window->e_key.unlock();
+			window->e_mouseScroll.unlock();
+    	}
+    	
         glfwPollEvents();
+	
+		for (auto glfwWindow : s_Windows) {
+			auto window = static_cast<Window *>(glfwGetWindowUserPointer(glfwWindow));
+		
+			window->e_mouseButton.lock();
+			window->e_mouseMove.lock();
+			window->e_resize.lock();
+			window->e_key.lock();
+			window->e_mouseScroll.lock();
+		}
     }
 
     void Window::onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods) {
-- 
GitLab