代码语言:javascript复制
#include <stdint.h>
#include <sys/time.h>
#include <stdexcept>
#include <mutex>
#include <thread>
#include "lightlog.h"
class SnowFlake {
private:
static const uint64_t m_start_time_stamp = 1480166465631; // 初始时间戳 给一个随机值
static const uint64_t m_sequence_bit = 12;
static const uint64_t m_machine_bit = 5;
static const uint64_t m_datacenter_bit = 5;
// 获取位数的最大值
static const uint64_t m_max_datacenter_num = -1 ^ (uint64_t(-1) << m_datacenter_bit);
static const uint64_t m_max_machine_num = -1 ^ (uint64_t(-1) << m_machine_bit);
static const uint64_t m_max_sequence_num = -1 ^ (uint64_t(-1) << m_sequence_bit);
// 下标
static const uint64_t m_machine_left = m_sequence_bit;
static const uint64_t m_datacenter_left = m_sequence_bit m_machine_bit;
static const uint64_t m_timestamp_left = m_sequence_bit m_machine_bit m_datacenter_bit;
uint64_t m_datacenterId;
uint64_t m_machineId;
uint64_t m_sequence;
uint64_t m_last_time_stamp;
std::mutex m_mtx;
uint64_t GetNextMill() {
uint64_t mill = GetNewTimeStamp();
while (mill <= m_last_time_stamp) {
mill = GetNewTimeStamp();
}
return mill;
}
uint64_t GetNewTimeStamp() {
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t time = tv.tv_sec;
time /= 1000;
time = (tv.tv_sec * 1000);
return time;
}
public:
SnowFlake(int datacenterId, int machineId)
{
// 参数校验
if ((uint64_t)datacenterId > m_max_datacenter_num || (uint64_t)datacenterId < 0) {
LLOG(ERRO) << "datacenterId can't be greater than max_datacenter_num_ or less than 0";
exit(0);
}
if ((uint64_t)machineId > m_max_machine_num || (uint64_t)machineId < 0) {
LLOG(ERRO) << "machineId can't be greater than max_machine_num_or less than 0";
exit(0);
}
m_datacenterId = datacenterId;
m_machineId = machineId;
m_sequence = 0L;
m_last_time_stamp = 0L;
}
uint64_t NextId() {
std::unique_lock<std::mutex> lock(m_mtx);
uint64_t curTimeStamp = GetNewTimeStamp();
if (curTimeStamp < m_last_time_stamp) {
LLOG(ERRO) << "clock moved backwards. refusing to generate id";
exit(0);
}
if (curTimeStamp == m_last_time_stamp) {
m_sequence = (m_sequence 1) & m_max_sequence_num;
if (m_sequence == 0) {
curTimeStamp = GetNextMill();
}
} else {
m_sequence = 0;
}
m_last_time_stamp = curTimeStamp;
return (curTimeStamp - m_start_time_stamp) << m_timestamp_left
| m_datacenterId << m_datacenter_left
| m_machineId << m_machine_left
| m_sequence;
}
};
void func(void* arg) {
SnowFlake* sf = (SnowFlake*)arg;
for (int i = 0; i < 10; i ) {
LLOG(INFO) << sf->NextId();
}
return;
}
int main() {
SnowFlake sf(2, 3);
std::thread t1(func, &sf);
t1.join();
return 0;
}
我的博客即将同步至腾讯云 社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1jaldbd5jadaj