* Timeout and interval functionality 4.x-dev

Thu, 23 Sep 2021 12:15:33 +0300

author
cemkalyoncu
date
Thu, 23 Sep 2021 12:15:33 +0300
branch
4.x-dev
changeset 1729
06588a526327
parent 1728
92bb193f0a6e
child 1730
fed904612a64

* Timeout and interval functionality

Source/Gorgon/Main.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Main.h file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/Main.cpp	Tue Aug 10 09:31:50 2021 +0300
+++ b/Source/Gorgon/Main.cpp	Thu Sep 23 12:15:33 2021 +0300
@@ -60,6 +60,10 @@
     
     std::mutex once_mtx;
     std::vector<std::function<void()>> once;
+    
+    size_t timeind = 0; //used for timeouts and intervals
+    std::map<size_t, std::pair<unsigned long, std::function<void()>>> timeouts;
+    std::map<size_t, std::tuple<unsigned long, unsigned long, std::function<void()>>> intervals;
 
 	bool exiting = false;
 
@@ -111,6 +115,43 @@
         }
         
         once.clear();
+        
+        for(auto &p : timeouts) {
+            if(p.second.first <= Time::internal::deltatime) {
+                p.second.first = 0;
+                p.second.second();
+            }
+            else {
+                p.second.first -= Time::internal::deltatime;
+            }
+        }
+        
+        for(auto it=timeouts.begin(); it != timeouts.end(); ) {
+            if(it->second.first == 0 || it->second.first == -1) {
+                it= timeouts.erase(it);
+            } else {
+                ++it;
+            }
+        }
+        
+        for(auto &p : intervals) {
+            if(std::get<0>(p.second) <= Time::internal::deltatime) {
+                std::get<0>(p.second) = std::get<1>(p.second) + std::get<0>(p.second) - Time::internal::deltatime;
+                std::get<2>(p.second)();
+            }
+            else {
+                std::get<0>(p.second) -= Time::internal::deltatime;
+            }
+        }
+        
+        for(auto it=intervals.begin(); it != intervals.end(); ) {
+            if(std::get<0>(it->second) == -1) {
+                it= intervals.erase(it);
+            } else {
+                ++it;
+            }
+        }
+        
 	}
 
 	void Render() {
@@ -152,4 +193,51 @@
         once.push_back(fn);
     }
     
+    size_t RegisterTimeout(unsigned long after, std::function<void()> fn) {
+        timeouts.insert({timeind, {after, fn}});
+        return timeind++; 
+    }
+    
+    void AlterTimeout(size_t timeout, unsigned long after) {
+        if(timeouts.count(timeout)) {
+            timeouts[timeout].first = after;
+        }
+    }
+    
+    void DisableTimeout(size_t timeout) {
+        if(timeouts.count(timeout)) {
+            //mark for erasure to ensure it is not deleted while
+            //being iterated.
+            timeouts[timeout].first = -1;
+        }
+    }    
+    
+    bool TimeoutExists(size_t timeout) {
+        return timeouts.count(timeout) != 0;
+    }
+
+    
+    size_t RegisterInterval(unsigned long after, std::function<void()> fn) {
+        intervals.insert({timeind, {after, after, fn}});
+        return timeind++; 
+    }
+    
+    void AlterInterval(size_t timeout, unsigned long after) {
+        if(intervals.count(timeout)) {
+            std::get<1>(intervals[timeout]) = after;
+        }
+    }
+    
+    void DisableInterval(size_t timeout) {
+        if(intervals.count(timeout)) {
+            //mark for erasure to ensure it is not deleted while
+            //being iterated.
+            std::get<0>(intervals[timeout]) = -1;
+        }
+    }
+    
+    bool IntervalExists(size_t timeout) {
+        return intervals.count(timeout) != 0;
+    }
+
 }
--- a/Source/Gorgon/Main.h	Tue Aug 10 09:31:50 2021 +0300
+++ b/Source/Gorgon/Main.h	Thu Sep 23 12:15:33 2021 +0300
@@ -10,63 +10,98 @@
 /// Root namespace for Gorgon Game Engine.
 namespace Gorgon {
 
-	/// @cond INTERNAL
-	namespace internal {
-		extern std::string systemname;
-	}
-	/// @endcond
+    /// @cond INTERNAL
+    namespace internal {
+        extern std::string systemname;
+    }
+    /// @endcond
 
-	/// Defines the abstract class of Runner. Runners take the control of the code
-	/// execution, calling any necessary functions as the events occur.
-	class Runner {
-	public:
-		/// Takes the control of the execution until Quit is called.
-		virtual void Run() = 0;
+    /// Defines the abstract class of Runner. Runners take the control of the code
+    /// execution, calling any necessary functions as the events occur.
+    class Runner {
+    public:
+        /// Takes the control of the execution until Quit is called.
+        virtual void Run() = 0;
 
-		/// Runs a single frame
-		virtual void Step() = 0;
+        /// Runs a single frame
+        virtual void Step() = 0;
 
-		/// Should quit after the current frame is completed for a graceful exit.
-		virtual void Quit() = 0;
-	};
+        /// Should quit after the current frame is completed for a graceful exit.
+        virtual void Quit() = 0;
+    };
 
-	/// Initializes the entire system except for graphics and UI. Graphics should
+    /// Initializes the entire system except for graphics and UI. Graphics should
     /// be initialized after a window is created and UI should be initialized last.
-	void Initialize(const std::string &systemname);
+    void Initialize(const std::string &systemname);
 
-	/// Returns the name of the current system
-	inline std::string GetSystemName() { return internal::systemname; }
+    /// Returns the name of the current system
+    inline std::string GetSystemName() { return internal::systemname; }
 
-	/// Performs various operations that are vital to system execution. These include
-	/// OS message handling, animation and sound progressions, time progression and 
-	/// delta time calculation. NextFrame function should be preferred if the frame delay
-	/// is tolerable.
-	void Tick();
+    /// Performs various operations that are vital to system execution. These include
+    /// OS message handling, animation and sound progressions, time progression and 
+    /// delta time calculation. NextFrame function should be preferred if the frame delay
+    /// is tolerable.
+    void Tick();
 
-	/// This function calls the starts the rendering pipeline. Rendering should be last
-	/// operation of a frame.
-	void Render();
+    /// This function calls the starts the rendering pipeline. Rendering should be last
+    /// operation of a frame.
+    void Render();
 
-	/// This function marks the end of current frame and starts the next one. This function calls
-	/// the Tick function at start of the next frame. Additionally, this function calls end of
-	/// frame tasks such as rendering. Before starting the next frame, a certain delay is performed.
-	/// This delay aims to set each frame duration to 16ms, this duration sets the frames per second
-	/// to 62.5. This delay greatly reduces the system load of simple games/applications.
-	void NextFrame();
+    /// This function marks the end of current frame and starts the next one. This function calls
+    /// the Tick function at start of the next frame. Additionally, this function calls end of
+    /// frame tasks such as rendering. Before starting the next frame, a certain delay is performed.
+    /// This delay aims to set each frame duration to 16ms, this duration sets the frames per second
+    /// to 62.5. This delay greatly reduces the system load of simple games/applications.
+    void NextFrame();
 
-	/// This method works similar to next frame, however, no delay is done. This function allows an
-	/// application to update the display and perform OS tasks while still continuing operation.
-	inline void UpdateFrame();
+    /// This method works similar to next frame, however, no delay is done. This function allows an
+    /// application to update the display and perform OS tasks while still continuing operation.
+    inline void UpdateFrame();
     
     /// Registers a function to be run at the start of the next frame.
     void RegisterOnce(std::function<void()> fn);
 
     /// Registers a function to be run at the start of the next frame.
-	template<class F_, class ...A_>
-	void RegisterOnce(F_ fn, A_ && ...args) {
+    template<class F_, class ...A_>
+    void RegisterOnce(F_ fn, A_ && ...args) {
         RegisterOnce(std::function<void()>(std::bind(fn, std::forward<A_>(args)...)));
     }
-
-	
-	extern Event<> BeforeFrameEvent;
+    
+    
+    /// Registers a function to be run after given time in milliseconds.
+    size_t RegisterTimeout(unsigned long after, std::function<void()> fn);
+    
+    /// Registers a function to be run after given time in milliseconds.
+    template<class F_, class ...A_>
+    size_t RegisterTimeout(unsigned long after, F_ fn, A_ && ...args) {
+        return RegisterTimeout(after, std::function<void()>(std::bind(fn, std::forward<A_>(args)...)));
+    }
+    
+    /// Alters timeout to fire after the given time from now in milliseconds
+    void AlterTimeout(size_t timeout, unsigned long after);
+    
+    void DisableTimeout(size_t timeout);
+    
+    bool TimeoutExists(size_t timeout);
+    
+    
+    /// Registers a function to be run regularly at given time in milliseconds.
+    size_t RegisterInterval(unsigned long after, std::function<void()> fn);
+    
+    /// Registers a function to be run regularly at given time in milliseconds.
+    /// Do not use this system for games! Use timebased simulation and animations.
+    template<class F_, class ...A_>
+    size_t RegisterInterval(unsigned long after, F_ fn, A_ && ...args) {
+        return RegisterInterval(after, std::function<void()>(std::bind(fn, std::forward<A_>(args)...)));
+    }
+    
+    /// Alters interval time in milliseconds
+    void AlterInterval(size_t timeout, unsigned long after);
+    
+    void DisableInterval(size_t timeout);
+    
+    bool IntervalExists(size_t timeout);
+    
+    
+    extern Event<> BeforeFrameEvent;
 }

mercurial