]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add cupsGetClock API.
authorMichael R Sweet <msweet@msweet.org>
Tue, 22 Oct 2024 20:25:50 +0000 (16:25 -0400)
committerMichael R Sweet <msweet@msweet.org>
Tue, 22 Oct 2024 20:25:50 +0000 (16:25 -0400)
cups/clock.c [new file with mode: 0644]
cups/testclock.c [new file with mode: 0644]

diff --git a/cups/clock.c b/cups/clock.c
new file mode 100644 (file)
index 0000000..51bb64b
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Monotonic clock API for CUPS.
+//
+// Copyright © 2024 by OpenPrinting.
+//
+// Licensed under Apache License v2.0.  See the file "LICENSE" for more
+// information.
+//
+
+#include "cups-private.h"
+
+
+//
+// Local globals...
+//
+
+static bool    cups_clock_init = false;// Clock initialized?
+static cups_mutex_t cups_clock_mutex = CUPS_MUTEX_INITIALIZER;
+                                       // Mutex to control access
+#ifdef _WIN32
+static ULONGLONG cups_first_tick;      // First tick count
+#else
+#  ifdef CLOCK_MONOTONIC
+static struct timespec cups_first_clock;// First clock value
+#  endif // CLOCK_MONOTONIC
+static struct timeval cups_first_time; // First time value
+#endif // _WIN32
+
+
+//
+// 'cupsGetClock()' - Get a monotonic clock value in seconds.
+//
+// This function returns a monotonically increasing clock value in seconds.  The
+// first call will always return 0.0.  Subsequent calls will return the number
+// of seconds that have elapsed since the first call, regardless of system time
+// changes, sleep, etc.  The sub-second accuracy varies based on the operating
+// system and hardware but is typically 10ms or better.
+//
+// @since CUPS 2.5@
+//
+
+double                                 // O - Elapsed seconds
+cupsGetClock(void)
+{
+  double       secs;                   // Elapsed seconds
+#ifdef _WIN32
+  ULONGLONG    curtick;                // Current tick count
+#else
+#  ifdef CLOCK_MONOTONIC
+  struct timespec curclock;            // Current clock value
+#  endif // CLOCK_MONOTONIC
+  struct timeval curtime;              // Current time value
+#endif // _WIN32
+
+
+  cupsMutexLock(&cups_clock_mutex);
+
+#ifdef _WIN32
+  // Get the current tick count in milliseconds...
+  curtick = GetTickCount64();
+
+  if (!cups_clock_init)
+  {
+    // First time through initialize the initial tick count...
+    cups_clock_init = true;
+    cups_first_tick = curtick;
+  }
+
+  // Convert ticks to seconds...
+  if (curtick < cups_first_tick)
+    secs = 0.0;
+  else
+    secs = 0.001 * (curtick - cups_first_tick);
+
+#else
+#  ifdef CLOCK_MONOTONIC
+  // Get the current tick count in milliseconds...
+  if (!clock_gettime(CLOCK_MONOTONIC, &curclock))
+  {
+    if (!cups_clock_init)
+    {
+      // First time through initialize the initial clock value...
+      cups_clock_init  = true;
+      cups_first_clock = curclock;
+    }
+
+    // Convert clock value to seconds...
+    if ((secs = curclock.tv_sec - cups_first_clock.tv_sec + 0.000000001 * (curclock.tv_nsec - cups_first_clock.tv_nsec)) < 0.0)
+      secs = 0.0;
+  }
+  else
+#  endif // CLOCK_MONOTONIC
+  {
+    gettimeofday(&curtime, /*tzp*/NULL);
+
+    if (!cups_clock_init)
+    {
+      // First time through initialize the initial clock value...
+      cups_clock_init = true;
+      cups_first_time = curtime;
+    }
+
+    // Convert time value to seconds...
+    if ((secs = curtime.tv_sec - cups_first_time.tv_sec + 0.000001 * (curtime.tv_usec - cups_first_time.tv_usec)) < 0.0)
+      secs = 0.0;
+  }
+#endif // _WIN32
+
+  cupsMutexUnlock(&cups_clock_mutex);
+
+  return (secs);
+}
diff --git a/cups/testclock.c b/cups/testclock.c
new file mode 100644 (file)
index 0000000..a69ec24
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Monotonic clock test program for CUPS.
+//
+// Copyright © 2024 by OpenPrinting.
+//
+// Licensed under Apache License v2.0.  See the file "LICENSE" for more
+// information.
+//
+
+#include "cups.h"
+#include "test-internal.h"
+#include <math.h>
+
+
+//
+// 'main()' - Main entry for clock tests.
+//
+
+int                                    // O - Exit status
+main(void)
+{
+  double       current;                // Current time
+
+
+  // Test clock values at 0, 1, 5, 10, and 30 seconds
+  testBegin("cupsGetClock(initial)");
+  current = cupsGetClock();
+  if (current == 0.0)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 0.0", current);
+
+  sleep(1);
+
+  testBegin("cupsGetClock(1 second)");
+  current = cupsGetClock();
+  if (fabs(current - 1.0) < 0.1)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 1.0 +/- 0.1", current);
+
+  sleep(4);
+
+  testBegin("cupsGetClock(5 seconds)");
+  current = cupsGetClock();
+  if (fabs(current - 5.0) < 0.1)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 5.0 +/- 0.1", current);
+
+  sleep(5);
+
+  testBegin("cupsGetClock(10 seconds)");
+  current = cupsGetClock();
+  if (fabs(current - 10.0) < 0.1)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 10.0 +/- 0.1", current);
+
+  sleep(20);
+
+  testBegin("cupsGetClock(30 seconds)");
+  current = cupsGetClock();
+  if (fabs(current - 30.0) < 0.1)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 30.0 +/- 0.1", current);
+
+  sleep(30);
+
+  testBegin("cupsGetClock(60 seconds)");
+  current = cupsGetClock();
+  if (fabs(current - 60.0) < 0.1)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 60.0 +/- 0.1", current);
+
+  sleep(60);
+
+  testBegin("cupsGetClock(120 seconds)");
+  current = cupsGetClock();
+  if (fabs(current - 120.0) < 0.1)
+    testEndMessage(true, "%g", current);
+  else
+    testEndMessage(false, "got %g, expected 120.0 +/- 0.1", current);
+
+  return (testsPassed ? 0 : 1);
+}