From bcc951f07e46571cec9a281ad36c2ded841e0dd1 Mon Sep 17 00:00:00 2001
From: Martin Hierholzer <martin.hierholzer@desy.de>
Date: Tue, 25 Sep 2018 12:52:07 +0200
Subject: [PATCH] Extended the PeriodicTrigger: - Timeout is now in
 milliseconds to allow more flexibility - Default timout can be specified in
 the constructor - Make sure the time interval is perfectly matched by using
 sleep_until instead of sleep_for

---
 Modules/include/PeriodicTrigger.h | 55 ++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/Modules/include/PeriodicTrigger.h b/Modules/include/PeriodicTrigger.h
index 289b3155..b2b751d0 100644
--- a/Modules/include/PeriodicTrigger.h
+++ b/Modules/include/PeriodicTrigger.h
@@ -7,27 +7,44 @@
 
 namespace ChimeraTK {
 
-/**
- * Simple periodic trigger that fires a variable once per second.
- * After configurable number of seconds it will wrap around
- */
-struct PeriodicTrigger : public ApplicationModule {
-    using ApplicationModule::ApplicationModule;
-
-    ScalarPollInput<int> timeout{this, "timeout", "s", "Timeout in seconds"};
-    ScalarOutput<int> tick{this, "tick", "", "Timer tick"};
-
-    void mainLoop()
-    {
+  /**
+   * Simple periodic trigger that fires a variable once per second.
+   * After configurable number of seconds it will wrap around
+   */
+  struct PeriodicTrigger : public ApplicationModule {
+
+      /** Constructor. In addition to the usual arguments of an ApplicationModule, the default timeout value is specified.
+       *  This value is used as a timeout if the timeout value is set to 0. The timeout value is in milliseconds. */
+      PeriodicTrigger(EntityOwner *owner, const std::string &name, const std::string &description,
+             const uint32_t defaultTimeout=1000, bool eliminateHierarchy=false, const std::unordered_set<std::string> &tags={})
+      : ApplicationModule(owner, name, description, eliminateHierarchy, tags),
+        defaultTimeout_(defaultTimeout)
+      {}
+
+      ScalarPollInput<uint32_t> timeout{this, "timeout", "ms", "Timeout in milliseconds. The trigger is sent once per the specified duration."};
+      ScalarOutput<uint64_t> tick{this, "tick", "", "Timer tick. Counts the trigger number starting from 0."};
+
+      void mainLoop() {
         tick = 0;
-        while (true) {
-            std::this_thread::sleep_for(std::chrono::seconds(1));
-            tick++;
-            tick %= timeout;
-            tick.write();
+        if(timeout = 0) timeout = defaultTimeout_;
+
+        std::chrono::time_point<std::chrono::steady_clock> t = std::chrono::steady_clock::now();
+
+        while(true) {
+          timeout.read();
+          t += static_cast<uint32_t>(timeout) * std::chrono::milliseconds();
+          std::this_thread::sleep_until(t);
+
+          tick++;
+          tick.write();
         }
-    }
-};
+      }
+
+    private:
+
+      uint32_t defaultTimeout_;
+
+  };
 }
 
 #endif // CHIMERATK_APPLICATION_CORE_PERIODIC_TRIGGER_H
-- 
GitLab