我打算发布并接受我自己想法的实现作为答案,因为它似乎是最实用的。
所以这就是解决方案:
- 每次构建时,在构建文件中添加一行包含以下数据的内容:
- 每次合并时,保留来自两个构建文件的行
- 构建数量是构建文件中行的总数。
构建文件的每一行都需要是唯一的。日期和时间使其几乎唯一。很少有两个人在同一时间在自己的分支上发出构建的情况。但是,这种情况可能会发生。因此,生成一个随机数并将其添加以减少该机会。
然而,存在一个问题。如果使用srand(time(NULL))
进行种子处理,那么由于两个构建被认为是在同一时间,生成的数字也可能相同。因此,可以使用不同的数字对随机数生成器进行种子处理,例如clock()
或gettimeofday()
的毫秒部分。即使没有随机生成,这些数字本身也可以放置在随机数的位置。
如果仍然有两行相同,我将应用鸵鸟算法。
更新:
我已经实现了它,一切都运行良好。最终,我使用clock_gettime(CLOCK_MONOTONIC, ...)
并打印此函数获得的纳秒作为随机数。我没有使用clock()
的原因是,由于程序非常短,它运行时间少于clock()
的分辨率,因此我一直得到0。
更新:
这是我编写的最终代码(其中一些部分从其他地方窃取!)。在某些平台上,您可能需要-lrt
。
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
struct timespec
{
long tv_sec;
long tv_nsec;
};
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
#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;
}
希望这对某些人有所帮助。
更新
使用了约9个月后,我可以说这非常有用。一些观察结果是:
- 在Windows上,
clock_gettime
的实现给出的最后一个元素非常小,同样的值半数以上出现。然而,它仍然使其更随机一些。
- 在Linux上,最后一个元素确实相当随机。
- 不时需要进行“构建”提交才能提交构建文件中的行以进行合并。但是,可以使用
git stash
避免此问题。
- 几乎每次使用此方法合并都会导致冲突,但解决它非常简单(只需将差异标记作为两个文件的行删除即可)。
wc -l
是你的好朋友。