I don\'t know if this is something common for people to do or not, but I personally always keep track of the number of times I built my code. That is, both the number of tim
I'm going to post and accept the implementation of my own idea as the answer, as it seems to be the most practical.
So here's the solution:
Each line of the build file needs to be unique. The date and time make that very nearly unique. It is very unlikely that two people issue a build on their own branch at the same time. However, it may happen. Therefore, a random number is generated and added to decrease that chance.
There is one problem though. If you seed srand
with time(NULL)
, then since both builds are supposedly at the same time, the generated number could also happen to be the same. Therefore, the random number generator could be seeded with a different number such as clock()
or the milliseconds part of gettimeofday()
. Even if not randomly generated, those numbers themselves could be put instead of a random number.
In the case where still two lines ended up the same, I'll apply the ostrich algorithm.
Update:
I implemented it and everything works fine. Finally, I used clock_gettime(CLOCK_MONOTONIC, ...)
and printed the nanoseconds obtained by this function as the random number. The reason I didn't use clock()
was that since the program was quite short, it ran less than the resolution of clock()
and therefore I kept getting 0s.
Update:
Here is the final code I wrote (with some parts of it stolen from somewhere else!). You may need -lrt on some platforms.
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#ifdef _WIN32
#include
struct timespec
{
long tv_sec;
long tv_nsec;
};
/* Note: I copy-pasted this from internet (https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows/5404467#5404467)
* I tweaked it to return nanoseconds instead of microseconds
* It is much more complete than just finding tv_nsec, but I'm keeping it for possible future use. */
LARGE_INTEGER getFILETIMEoffset(void)
{
SYSTEMTIME s;
FILETIME f;
LARGE_INTEGER t;
s.wYear = 1970;
s.wMonth = 1;
s.wDay = 1;
s.wHour = 0;
s.wMinute = 0;
s.wSecond = 0;
s.wMilliseconds = 0;
SystemTimeToFileTime(&s, &f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
return t;
}
int clock_gettime(int X, struct timespec *tv)
{
LARGE_INTEGER t;
FILETIME f;
double microseconds;
static LARGE_INTEGER offset;
static double frequencyToNanoseconds;
static int initialized = 0;
static BOOL usePerformanceCounter = 0;
if (!initialized)
{
LARGE_INTEGER performanceFrequency;
initialized = 1;
usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
if (usePerformanceCounter)
{
QueryPerformanceCounter(&offset);
frequencyToNanoseconds = (double)performanceFrequency.QuadPart/1000000000.0;
}
else
{
offset = getFILETIMEoffset();
frequencyToNanoseconds = 0.010;
}
}
if (usePerformanceCounter)
QueryPerformanceCounter(&t);
else
{
GetSystemTimeAsFileTime(&f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
}
t.QuadPart -= offset.QuadPart;
microseconds = (double)t.QuadPart/frequencyToNanoseconds;
t.QuadPart = microseconds;
tv->tv_sec = t.QuadPart/1000000000;
tv->tv_nsec = t.QuadPart%1000000000;
return 0;
}
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 0 /* not used anyway */
#endif
#endif
int main(int argc, char **argv)
{
time_t now_sec;
struct tm *now;
FILE *bout;
struct timespec now_clk;
if (argc < 2)
{
printf("Usage: %s build_file_name\n\n", argv[0]);;
return EXIT_FAILURE;
}
bout = fopen(argv[1], "a");
if (!bout)
{
printf("Could not open file: %s\n\n", argv[1]);
return EXIT_FAILURE;
}
time(&now_sec);
now = gmtime(&now_sec);
fprintf(bout, "%02d/%02d/%04d %02d:%02d:%02d", now->tm_mday, now->tm_mon+1, now->tm_year+1900, now->tm_hour, now->tm_min, now->tm_sec);
clock_gettime(CLOCK_MONOTONIC, &now_clk);
fprintf(bout, " %ld\n", now_clk.tv_nsec);
return EXIT_SUCCESS;
}
Hopefully this will be of help to someone.
After ~9 months of using this, I can say this has been quite useful. Some observations are:
clock_gettime
is quite small, half of the times with the same value. Nevertheless, it still makes it a bit more random.git stash
.