#include #include #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; }