Skip to content

Commit

Permalink
Add cupsGetClock API.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Oct 22, 2024
1 parent 0350eba commit 3395443
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 0 deletions.
112 changes: 112 additions & 0 deletions cups/clock.c
Original file line number Diff line number Diff line change
@@ -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);
}
88 changes: 88 additions & 0 deletions cups/testclock.c
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 3395443

Please sign in to comment.