This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/src/id_generator/id_generator.cpp

78 lines
2.4 KiB
C++

#include <time.h>
#include <string.h>
#include "id_generator.h"
#include "stellar.h"
struct id_generator
{
uint8_t device_base; // 5bit [0, 31]
uint8_t device_offset; // 7bit [0, 127]
uint64_t device_id; // 12bit [0, 4095] ( base << 7 | offset )
uint64_t thread_volatile[MAX_THREAD_NUM];
};
struct id_generator global_id_generator;
/*
* device_base (5bit) : [0, 31]
* device_offset (7bit) : [0, 127]
* device_id (12bit) : (base << 7 | offset)
*
* return 0: success
* return -1: failed
*/
int id_generator_init(uint8_t device_base, uint8_t device_offset)
{
memset(&global_id_generator, 0, sizeof(struct id_generator));
if (device_base > 31)
{
ID_GENERATOR_LOG_ERROR("device_base %u is invalid, range [0, 31]", device_base);
return -1;
}
if (device_offset > 127)
{
ID_GENERATOR_LOG_ERROR("device_offset %u is invalid, range [0, 127]", device_offset);
return -1;
}
global_id_generator.device_base = device_base;
global_id_generator.device_offset = device_offset;
global_id_generator.device_id = ((global_id_generator.device_base << 7) | global_id_generator.device_offset) & 0xFFF;
ID_GENERATOR_LOG_DEBUG("device_base: %u, device_offset: %u, device_id: %u",
global_id_generator.device_base,
global_id_generator.device_offset,
global_id_generator.device_id);
return 0;
}
/*
* 高位 --- 低位
*
* +------+------------------+----------------+------------------------+---------------------------+
* | 1bit | 12bit device_id | 8bit thread_id | 28bit timestamp in sec | 15bit sequence per thread |
* +------+------------------+----------------+------------------------+---------------------------+
*/
uint64_t id_generator_alloc()
{
#define MAX_ID_PER_THREAD (32768)
#define MAX_ID_BASE_TIME (268435456L)
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); // must be realtime
uint64_t thread_index = stellar_get_current_thread_index();
uint64_t global_id = 0;
uint64_t id_per_thread = (global_id_generator.thread_volatile[thread_index]++) % MAX_ID_PER_THREAD;
uint64_t id_base_time = ts.tv_sec % MAX_ID_BASE_TIME;
global_id = (global_id_generator.device_id << 51) |
(thread_index << 43) |
(id_base_time << 15) |
(id_per_thread);
return global_id;
}