فهرست منبع

添加CUniqueId类,用于生成唯一索引值。

Jeff 6 سال پیش
والد
کامیت
445c6776e8
2فایلهای تغییر یافته به همراه156 افزوده شده و 0 حذف شده
  1. 95 0
      source/hook/WxAdoInterface/CUniqueId.cpp
  2. 61 0
      source/hook/WxAdoInterface/CUniqueId.h

+ 95 - 0
source/hook/WxAdoInterface/CUniqueId.cpp

@@ -0,0 +1,95 @@
+#include "CUniqueId.h"
+#if defined(__GUNC__)
+#include <sys/time.h>
+#include <unistd.h>
+#define EPOCHFILETIME 11644473600000000ULL
+#else
+#include <Windows.h>
+#include <time.h>
+#define EPOCHFILETIME 11644473600000000Ui64
+#endif
+unsigned long long CUniqueId::_lasttimestamp = 0;
+
+unsigned long long get_time()
+{
+#ifdef __GUNC__
+	struct timeval tv;
+	gettimeofday(&tv, NULL);
+	uint64 time = tv.tv_usec;
+	time /= 1000;
+	time += ((uint64_t)tv.tv_sec * 1000);
+	return time;
+#else
+	FILETIME filetime;
+	uint64_t time = 0;
+	GetSystemTimeAsFileTime(&filetime);
+
+	time |= filetime.dwHighDateTime;
+	time <<= 32;
+	time |= filetime.dwLowDateTime;
+
+	time /= 10;
+	time -= EPOCHFILETIME;
+	return time / 1000;
+#endif
+}
+
+CUniqueId::CUniqueId() :_workerId(0), _datacenterId(0), _sequence(0)
+{
+}
+
+
+CUniqueId::~CUniqueId()
+{
+}
+
+unsigned long long CUniqueId::next_timestamp()
+{
+	__time64_t timestamp = get_time();
+	while (timestamp <= _lasttimestamp)
+	{
+		timestamp = get_time();
+	}
+	return timestamp;
+}
+
+void CUniqueId::setWorkerId(const unsigned char &workerId)
+{
+	_workerId = workerId;
+}
+
+void CUniqueId::setDatacenterId(const unsigned char & datacenterId)
+{
+	_datacenterId = datacenterId;
+}
+
+unsigned long long CUniqueId::get_unique_id()
+{
+#ifndef USE_C0X
+	std::unique_lock <std::mutex> lock{ _mutex };
+	__time64_t timestamp = 0;
+#else
+	// 获取当前日历时间(1900-01-01开始的Unix时间戳);
+	static std::atomic<__time64_t> timestamp = 0;
+#endif
+	timestamp = get_time();
+	if (timestamp < _lasttimestamp)
+		return -1;
+
+	if (timestamp == _lasttimestamp)
+	{// 相同时间戳下,序列值自增(最大4095);
+		_sequence = (++_sequence) & _sequenceMask;
+		if (_sequence == 0)
+		{// 该时间戳内已用完,;
+			timestamp = next_timestamp();
+		}
+	}
+	else
+	{// 不同时间戳下,重置序列值;
+		_sequence = 0;
+	}
+
+	_lasttimestamp = timestamp;
+
+	return ((timestamp - _twepoch) << _timestampleftShift) | (_datacenterId << _datacenterIdShift) | (_workerId << _workerIdBits) | _sequence;
+}

+ 61 - 0
source/hook/WxAdoInterface/CUniqueId.h

@@ -0,0 +1,61 @@
+#pragma once
+
+#include <atomic>
+#include <mutex>
+
+class CUniqueId
+{
+public:
+	CUniqueId();
+	CUniqueId(const unsigned char &workerId, const unsigned char &datacenterId)
+	{
+		_workerId = workerId;
+		_datacenterId = datacenterId;
+	}
+	~CUniqueId();
+
+private:
+	// 开始utc时间戳(2018-01-01 00:00:00.000);
+	const unsigned long long _twepoch = 1514736000000;
+	// 工作者占用位数;
+	const unsigned char _workerIdBits = 5;
+	// 支持的最大工作者id,结果是31;
+	const unsigned char _maxWorkerId = -1L ^ (-1L << _workerIdBits);
+	// 数据中心占用位数;
+	const unsigned char _datacenterIdBits = 5;
+	// 支持的最大数据中心id,结果是31;
+	const unsigned char _maxDatacenterId = -1L ^ (-1L << _datacenterIdBits);
+	// 序列占用位数;
+	const unsigned char _sequenceBits = 12;
+
+	// 工作者向左移12位;
+	const unsigned char _workerIdShift = _sequenceBits;
+	// 数据中心向左移17位;
+	const unsigned char _datacenterIdShift = _workerIdShift + _workerIdBits;
+	// 时间戳向左移22位;
+	const unsigned char _timestampleftShift = _datacenterIdShift + _datacenterIdBits;
+	// 生成的序列掩码,4095;
+	const unsigned short _sequenceMask = -1L ^ (-1L << _sequenceBits);
+
+	// 工作id; 
+	unsigned char _workerId;
+	// 数据中心id;
+	unsigned char _datacenterId;
+	// 序列值;
+	unsigned short _sequence;
+	// 上一次的时间戳;
+	static unsigned long long _lasttimestamp;
+
+#ifndef USE_C0X
+	// 如果不是c++11的话,不能使用atomic;
+	std::mutex _mutex;
+#endif
+private:
+	unsigned long long next_timestamp();
+
+public:
+	void setWorkerId(const unsigned char &workerId);
+	void setDatacenterId(const unsigned char &datacenterId);
+	unsigned long long get_unique_id();
+};
+