This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Poco test using clock_gettime() and gettimeofday()


I'm trying to get the (rather extensive) testsuite for poco-1.4.7 passing - or at least satisfying myself that any failures are not due to a Cygwin problem. The last test I have to worry about is 'testDequeue' from the Foundation testsuite.

The Poco code uses two clock classes, one that uses clock_getttime() and the other uses gettimeofday(). The test creates two timestamps using the two clock classes, both 0.1 seconds in the future. clock_gettime() is polled repeatedly until the timestamp is reached. Then the other timestamp is checked (using gettimeofday()) to ensure that 0.1 seconds has elapsed on this clock also.

I've managed to condense this down into the sample programme attached. This always passes in Fedora 20, but passes or fails randomly in Cygwin.

I'm not convinced that the test is valid. Poco seems to be making assumptions about clock_gettime() and gettimeofday() that simply aren't guaranteed to hold - but obviously do in Fedora at least. For instance, the test must be assuming that either the accuracy of the two routines is identical, or be making assumptions about rounding in the less accurate routine.

I think it would be better to patch the test so that it uses clock_gettime() exclusively (and not gettimeofday() at all), and then this problem will disappear. But I thought I would submit it here to see what you thought before raising a ticket with the Poco developers.

What do you think?

Dave.

// timer_test.cpp
// Compares two clocks. Based on the 'testDequeue' check in Poco 1.4.7.
//
// g++ -o timer_test timer_test.cpp
// while [ true ]; do
//   ./timer_test | grep FAIL
// done
//
// On Fedora 20, the programme never fails. However, in Cygwin the programme
// passes or fails randomly.
#include <iostream>
#include <time.h>
#include <sys/time.h>

// This class acts as a base class for our two clocks. Each clock is
// constructed with a duration, which is the number of microseconds in the
// future to take as the timestamp. A value of zero sets the clock to the
// current time, and negative numbers are in the past.
//
// The class provides a function called Elapsed(), which returns the number
// of microseconds until the timestamp. If the value returned is negative
// then the timestamp is in the past.
class ClockBase
{
public:
	typedef long long ClockVal;
	typedef long long ClockDiff;

	virtual ~ClockBase() {}
	virtual ClockDiff Elapsed() const = 0;
	static ClockDiff Resolution() { return 1000000; }

protected:
	ClockVal clockval;
};

// This clock uses clock_gettime().
class ClockGetTime : public ClockBase
{
public:
	explicit ClockGetTime(ClockDiff d)
	{
		struct timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		clockval = ClockVal(ts.tv_sec) * Resolution() + ts.tv_nsec / 1000 + d;
	}

	virtual ClockDiff Elapsed() const
	{
		ClockGetTime now(0);
		return now.clockval - clockval;
	}
};

// This clock uses gettimeofday().
class GetTimeOfDay : public ClockBase
{
public:
	explicit GetTimeOfDay(ClockDiff d)
	{
		struct timeval tv;
		gettimeofday(&tv, NULL);
		clockval = ClockVal(tv.tv_sec) * Resolution() + tv.tv_usec + d;
	}

	virtual ClockDiff Elapsed() const
	{
		GetTimeOfDay now(0);
		return now.clockval - clockval;
	}
};

int main()
{
	// Define a point in time, 0.1 seconds in the future. This is done twice,
	// using our two classes.
	const ClockBase::ClockDiff duration = 10000; // 0.1s
	const GetTimeOfDay target1(duration);
	const ClockGetTime target2(duration);

	// Wait until the 0.1 seconds has elapsed. We use the class that calls
	// clock_gettime().
	while(target2.Elapsed() < 0);

	// Now check the amount of time that has passed using the other class.
	// Poco 1.4.7 assumes that if 0.1 seconds has passed on the first clock,
	// then 0.1 seconds must have passed on the second clock too. This
	// assumes a great deal about the relative accuracy of the two clocks,
	// and how any rounding is performed in whichever clock is less accurate.
	if (target1.Elapsed() >= 0)
		std::cout << "PASSED" << std::endl;
	else
		std::cout << "FAILED" << std::endl;

	return 0;
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]