void resync(){
//first lets make some objects to be used later
struct sysinfo memInfo;//struct to check memory usage
int iteration = 0;//iteration counter
uint64_t nextTimeSeconds;
uint64_t nextTimeMicroSeconds;
//Sleep until x minute to sync/run chassis simultaneously
using std::chrono::system_clock;
std::time_t tt = system_clock::to_time_t (system_clock::now());
struct std::tm * ptm = std::localtime(&tt);
std::cout << "Waiting for the next minute to begin...\n";
++ptm->tm_min;
ptm->tm_sec=0;
std::this_thread::sleep_until (system_clock::from_time_t (mktime(ptm)));
//do some arithemtic to ensure there are no nonzero decimals on our time object
chrono::high_resolution_clock::time_point currTime = chrono::high_resolution_clock::now();
chrono::high_resolution_clock::time_point nextTime;
auto currTimeNanoDecimals = (chrono::duration_cast<chrono::nanoseconds>(currTime.time_since_epoch()).count()) -((chrono::duration_cast<chrono::seconds>(currTime.time_since_epoch()).count()) * 1000000000); //find decimals for flooring
currTime = currTime - chrono::nanoseconds(currTimeNanoDecimals); //floor to second
//main program loop
for(int j = 0; j < (runs); j++) //change this to change how many iterations the FPGA timestamp resyncs for
{
nextTime = currTime + chrono::seconds(1); //incrementing for next time
nextTimeSeconds = chrono::duration_cast<chrono::seconds>(nextTime.time_since_epoch()).count();
nextTimeMicroSeconds = nextTimeSeconds * 1000000;
cout << " Time cycle "<< chrono::duration_cast<chrono::microseconds>(currTime.time_since_epoch()).count() << " to "<< nextTimeMicroSeconds<<"\n\n";
myfile<<iteration<<",";
myfile<< nextTimeSeconds<<","; //nextMicroSec
//Add easy to read time here
writeTime();
chrono::high_resolution_clock::time_point epochTime = chrono::high_resolution_clock::now();
double epocTime = chrono::duration_cast<chrono::nanoseconds>(epochTime.time_since_epoch()).count();
epocTime /= 1E9;
myfile<<fixed<<epocTime<<",";
this_thread::sleep_until(currTime + chrono::nanoseconds(500000000));
ntpSync();
//change some values before next iteration
currTime = nextTime; //comment out if testing with one sec
iteration++;
this_thread::sleep_until(nextTime);
cout<<"Current time at end : "<< chrono::duration_cast<chrono::microseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()<<endl;
}
}
// MAIN
int main(int argc, char *argv[])
{
init();
myfile<<"iteration, Next Second, current time, current time (epoch), Offset between the local cloak and the source at last measurement [actual measure offset]"<<"\n";
resync();
//close out the files
myfile.close();
return 0;
}
This is from just the ntpsync code without reading the other registers. Ive run it with the writeTime commented out so that can be ignored/isnt the culprint.
I thought it may be the wait until part but it freezes inconsistently (due to it freezing at random print statements).
One problem is that you're reading the current time multiple times throughout the code and it can change from one to the next. For example, at line 11, you read the time. Suppose it's 3:29.999999999. Lines 14 & 15 computer 3:30 and line 16 waits until 3:30. But by then, maybe the clock time is 3:30.000001. If sleep_until() doesn't account for the possibility of being given a time in the past, the duration could overflow and cause you to sleep for a very VERY long time.
Along the same line 46 assumes that the each iteration of the loop completes in less that 500ms. If it doesn't (which might happen if there's a network error, or if the writes to myfile get delayed, or the system clock gets updated), then you'll be asking to sleep until time that has already passed.
lines 10-16 only run once and it never freezes there. Everything executes/is on the microsecond scale except for the sleep until so that shouldnt be an issue.
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <chrono>
#include <ratio>
#include <thread>
usingnamespace std;
int runs = 1000;
int numSyncCalls = 0;
void ntpSync()
{
numSyncCalls++;
char ntp[] = "oojit";
FILE *jitter;
char line[100];
int numLinesRead = 0;
//system("chronyc sources|cat > offset.txt");
jitter = fopen("offset.txt", "r");
while ( fgets(line,sizeof(line),jitter) ) {
++numLinesRead;
if ( strstr(line,ntp) ) {
char *start = strpbrk(line,"+-");
//myfile<<start;
}
}
fclose(jitter);
}
void resync()
{
//first lets make some objects to be used later
//struct sysinfo memInfo; //struct to check memory usage
int iteration = 0; //iteration counter
uint64_t nextTimeSeconds;
uint64_t nextTimeMicroSeconds;
//Sleep until x minute to sync/run chassis simultaneously
using std::chrono::system_clock;
std::time_t tt = system_clock::to_time_t(system_clock::now());
struct std::tm * ptm = std::localtime(&tt);
std::cout << "Waiting for the next minute to begin...\n";
++ptm->tm_min;
ptm->tm_sec = 0;
std::this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
//do some arithemtic to ensure there are no nonzero decimals on our time object
chrono::high_resolution_clock::time_point currTime = chrono::high_resolution_clock::now();
chrono::high_resolution_clock::time_point nextTime;
auto currTimeNanoDecimals = (chrono::duration_cast<chrono::nanoseconds > (currTime.time_since_epoch()).count()) -
( (chrono::duration_cast<chrono::seconds> (currTime.time_since_epoch()).count()) * 1000000000); //find decimals for flooring
currTime = currTime - chrono::nanoseconds(currTimeNanoDecimals); //floor to second
//main program loop
for (int j = 0; j < (runs); j++) //change this to change how many iterations the FPGA timestamp resyncs for
{
nextTime = currTime + chrono::seconds(1); //incrementing for next time
nextTimeSeconds = chrono::duration_cast<chrono::seconds>(nextTime.time_since_epoch()).count();
nextTimeMicroSeconds = nextTimeSeconds * 1000000;
cout << " Time cycle "
<< chrono::duration_cast<chrono::microseconds>(currTime.time_since_epoch()).count()
<< " to "
<< nextTimeMicroSeconds
<< "\n\n";
//myfile << iteration << ",";
//myfile << nextTimeSeconds << ","; //nextMicroSec
//Add easy to read time here
//writeTime();
chrono::high_resolution_clock::time_point epochTime = chrono::high_resolution_clock::now();
double epocTime = chrono::duration_cast<chrono::nanoseconds>(epochTime.time_since_epoch()).count();
epocTime /= 1E9;
//myfile << fixed << epocTime << ",";
this_thread::sleep_until(currTime + chrono::nanoseconds(500000000));
ntpSync();
//change some values before next iteration
currTime = nextTime; //comment out if testing with one sec
iteration++;
this_thread::sleep_until(nextTime);
cout << "Current time at end : "
<< chrono::duration_cast<chrono::microseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()
<< endl;
}
}
// MAIN
int main(int argc, char *argv[])
{
//init();
//myfile << "iteration, Next Second, current time, current time (epoch), "
// "Offset between the local cloak and the source at last "
// "measurement [actual measure offset]"
// << "\n";
resync();
//close out the files
//myfile.close();
return 0;
}
The high_resolution_clock is not implemented consistently across different standard library implementations, and its use should be avoided. It is often just an alias for std::chrono::steady_clock or std::chrono::system_clock, but which one it is depends on the library or configuration. When it is a system_clock, it is not monotonic (e.g., the time can go backwards). For example, for gcc's libstdc++ it is system_clock, for MSVC it is steady_clock, and for clang's libc++ it depends on configuration.
Generally one should just use std::chrono::steady_clock or std::chrono::system_clock directly instead of std::chrono::high_resolution_clock: use steady_clock for duration measurements, and system_clock for wall-clock time.
So yeah, since you're on Linux, you've got a system_clock (which is NOT monotonic).
If your code doesn't deal with negatives as dhayden surmises, I wouldn't be surprised if you don't end up waiting for a billion seconds at some point, instead of a billion nanoseconds.
It appears that @Dhayden and salem c were right and I need to eat my words. Somehow my clock randomly jumps a couple seconds and since it goes past the wait time, it freezes. I was confusing where it froze from the csv due to there being a lag time from the code executing and it actually appearing in the csv.