Чтобы генерировать глобальные уникальные идентификаторы, мне нужно что-то вроде метки времени их создания. Но эти идентификаторы могут быть сгенерированы непосредственно после друг друга в исходном коде. Таким образом, время в миллисекундах недостаточно точное и может непреднамеренно создать одинаковые идентификаторы.
Поэтому мне нужна достаточно точная временная метка, чтобы она менялась при каждом получении. Я думаю о циклах процессора, но я не знаю, есть ли способ получить эту информацию.
Так как это для игры в реальном времени, выборка метки времени связана с производительностью. Более того, он кросс-платформенный, совместимый с Linux, Windows и Mac, поэтому, конечно, временная метка тоже должна быть. Если нет стандартного способа, я мог бы жить с тремя отличительными решениями для систем.
Отметки времени не очень хороши для этого, если вы не гарантированно имеете источник времени с высоким разрешением. Некоторые системы имеют это, другие нет.
В частности, если система имеет несколько ЦП, «счетчик меток времени» для каждого ЦП может не синхронизироваться, поэтому вы можете получить дубликаты просто потому, что количество тактов на одном ЦП «отстает» от количества тактов на другом ЦП.
В системе POSIX вы можете использовать clock_gettime
который имеет наносекундное разрешение, и должен быть достаточно быстрым.
Я написал этот код, чтобы проверить это:
#include <iostream>
#include <sys/time.h>
using namespace std;
int main ()
{
timespec ts[100];
for(auto &t : ts)
clock_gettime(CLOCK_REALTIME, &t);
timespec old_ts = {0};
for(auto &t : ts)
{
long diff = 0;
if (old_ts.tv_sec)
{
diff = t.tv_nsec - old_ts.tv_nsec;
}
cout << "ts.nsec: " << t.tv_nsec << " diff=" << diff << endl;
old_ts = t;
}
return 0;
}
Редактировать:
Конечно, самая простая форма уникального идентификатора — это 64-битный атомный счетчик — он самый быстрый и простой. Предполагая, что у вас есть возможности C ++ 11:
#include <atomic>
typdef long long int id_type;
std::atomic<id_type> current_id;
id_type get_next_id()
{
return current_id.fetch_add(1);
}
Не уверен, что Visual Studio имеет атомарный, но вы могли бы использовать InterlockedINcrement64()
:
InterlockedIncrement64(¤t);
Других решений пока нет …