BIN
PHP/Release/php7.3nts-vc15-php_snowdrift.zip
Normal file
BIN
PHP/Release/php7.3nts-vc15-php_snowdrift.zip
Normal file
Binary file not shown.
BIN
PHP/Release/php7.4nts-vc15-php_snowdrift.zip
Normal file
BIN
PHP/Release/php7.4nts-vc15-php_snowdrift.zip
Normal file
Binary file not shown.
BIN
PHP/Release/php8.0nts-vs16-php_snowdrift.zip
Normal file
BIN
PHP/Release/php8.0nts-vs16-php_snowdrift.zip
Normal file
Binary file not shown.
@@ -1,18 +1,13 @@
|
||||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
// If your extension references something external, use ARG_WITH
|
||||
// ARG_WITH("snowdrift", "for snowdrift support", "no");
|
||||
|
||||
// Otherwise, use ARG_ENABLE
|
||||
ARG_ENABLE("snowdrift", "enable snowdrift support", "no");
|
||||
ARG_ENABLE('snowdrift', 'snowdrift support', 'no');
|
||||
|
||||
if (PHP_SNOWDRIFT != "no") {
|
||||
AC_DEFINE('HAVE_SNOWDRIFT', 1, 'snowdrift support enabled');
|
||||
snowdrift_source_file="snowdrift.c\
|
||||
src/snowflake/snowflake.c\
|
||||
src/snowflake/shm.c\
|
||||
src/snowflake/spinlock.c
|
||||
"
|
||||
EXTENSION("snowdrift", $snowdrift_source_file, PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
src/snowflake/spinlock.c"
|
||||
EXTENSION("snowdrift", snowdrift_source_file, null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
|
||||
}
|
||||
|
||||
|
||||
@@ -66,9 +66,8 @@ static int snowdrift_init()
|
||||
shmctx.size = wid_num * sizeof(snowflake);
|
||||
if (shm_alloc(&shmctx) == -1)
|
||||
{
|
||||
return FAILURE;
|
||||
return FAILURE;
|
||||
}
|
||||
bzero(shmctx.addr, wid_num * sizeof(snowflake));
|
||||
sf = (snowflake *)shmctx.addr;
|
||||
int i;
|
||||
for (i = 0; i < wid_num; i++)
|
||||
@@ -92,7 +91,6 @@ static int snowdrift_init()
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
bzero(shmctx.addr, sizeof(snowflake));
|
||||
sf = (snowflake *)shmctx.addr;
|
||||
sf->Method = SD_G(Method);
|
||||
sf->BaseTime = SD_G(BaseTime);
|
||||
@@ -138,7 +136,7 @@ PHP_METHOD(snowdrift, NextNumId)
|
||||
{
|
||||
zend_long num = 1;
|
||||
zend_long wid = SD_G(WorkerId);
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &num, &wid) == FAILURE)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &num, &wid) == FAILURE)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -1,65 +1,105 @@
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include "shm.h"
|
||||
|
||||
#ifdef MAP_ANON
|
||||
#ifdef WIN32
|
||||
#define NAME "SnowDrift"
|
||||
static HANDLE hMapFile;
|
||||
|
||||
int shm_alloc(struct shm *shm)
|
||||
{
|
||||
shm->addr = (void *)mmap(NULL, shm->size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
int shm_alloc(struct shm* shm) {
|
||||
hMapFile = CreateFileMapping(
|
||||
INVALID_HANDLE_VALUE,
|
||||
NULL,
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
shm->size,
|
||||
NAME
|
||||
);
|
||||
|
||||
if (shm->addr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (hMapFile == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
LPVOID pBuffer = (LPTSTR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, shm->size);
|
||||
|
||||
if (pBuffer == NULL)
|
||||
{
|
||||
CloseHandle(hMapFile);
|
||||
return 0;
|
||||
}
|
||||
memset((char*)pBuffer, 0, shm->size);
|
||||
shm->addr = (void*)pBuffer;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shm_free(struct shm *shm)
|
||||
void shm_free(struct shm* shm) {
|
||||
UnmapViewOfFile(shm->addr);
|
||||
CloseHandle(hMapFile);
|
||||
}
|
||||
|
||||
#elif defined(MAP_ANON)
|
||||
|
||||
int shm_alloc(struct shm* shm)
|
||||
{
|
||||
if (shm->addr)
|
||||
{
|
||||
munmap((void *)shm->addr, shm->size);
|
||||
}
|
||||
shm->addr = (void*)mmap(NULL, shm->size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
|
||||
if (shm->addr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bzero(shm->addr, shm->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shm_free(struct shm* shm)
|
||||
{
|
||||
if (shm->addr)
|
||||
{
|
||||
munmap((void*)shm->addr, shm->size);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int shm_alloc(struct shm *shm)
|
||||
int shm_alloc(struct shm* shm)
|
||||
{
|
||||
int fd;
|
||||
int fd;
|
||||
|
||||
fd = open("/dev/zero", O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
fd = open("/dev/zero", O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
shm->addr = (void *)mmap(NULL, shm->size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
shm->addr = (void*)mmap(NULL, shm->size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
close(fd);
|
||||
close(fd);
|
||||
|
||||
if (shm->addr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (shm->addr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bzero(shm->addr, shm->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shm_free(struct shm *shm)
|
||||
void shm_free(struct shm* shm)
|
||||
{
|
||||
if (shm->addr)
|
||||
{
|
||||
munmap((void *)shm->addr, shm->size);
|
||||
}
|
||||
if (shm->addr)
|
||||
{
|
||||
munmap((void*)shm->addr, shm->size);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,125 +1,127 @@
|
||||
#ifdef WIN32
|
||||
#include "windows.h"
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "snowflake.h"
|
||||
#include "spinlock.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
// static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake);
|
||||
static inline uint64_t NextOverCostId(snowflake *flake);
|
||||
static inline uint64_t NextNormalId(snowflake *flake);
|
||||
static inline uint64_t GetCurrentTimeTick(snowflake *flake);
|
||||
static inline uint64_t GetNextTimeTick(snowflake *flake);
|
||||
static inline uint64_t CalcId(snowflake *flake);
|
||||
static inline uint64_t CalcTurnBackId(snowflake *flake);
|
||||
static inline uint64_t GetCurrentTime();
|
||||
static inline uint64_t NextOverCostId(snowflake* flake);
|
||||
static inline uint64_t NextNormalId(snowflake* flake);
|
||||
static inline uint64_t GetCurrentTimeTick(snowflake* flake);
|
||||
static inline uint64_t GetNextTimeTick(snowflake* flake);
|
||||
static inline uint64_t CalcId(snowflake* flake);
|
||||
static inline uint64_t CalcTurnBackId(snowflake* flake);
|
||||
static inline uint64_t GetSysCurrentTime();
|
||||
|
||||
int ncpu;
|
||||
uint16_t spin = 2048;
|
||||
uint32_t pid = 0;
|
||||
|
||||
void Config(snowflake *flake)
|
||||
void Config(snowflake* flake)
|
||||
{
|
||||
if (pid == 0)
|
||||
{
|
||||
pid = (uint32_t)getpid();
|
||||
#if defined(WIN32)
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo(&sysInfo);
|
||||
ncpu = sysInfo.dwNumberOfProcessors;
|
||||
if (pid == 0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
pid = (uint32_t)GetCurrentProcessId();
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo(&sysInfo);
|
||||
ncpu = sysInfo.dwNumberOfProcessors;
|
||||
#else
|
||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
pid = (uint32_t)getpid();
|
||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#endif
|
||||
if (ncpu <= 0)
|
||||
{
|
||||
ncpu = 1;
|
||||
}
|
||||
}
|
||||
if (flake->BaseTime == 0)
|
||||
{
|
||||
flake->BaseTime = 1582136402000;
|
||||
}
|
||||
else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetCurrentTime())
|
||||
{
|
||||
perror("BaseTime error.");
|
||||
exit(1);
|
||||
}
|
||||
if (ncpu <= 0)
|
||||
{
|
||||
ncpu = 1;
|
||||
}
|
||||
}
|
||||
if (flake->BaseTime == 0)
|
||||
{
|
||||
flake->BaseTime = 1582136402000;
|
||||
}
|
||||
else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetSysCurrentTime())
|
||||
{
|
||||
perror("BaseTime error.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 2.WorkerIdBitLength
|
||||
if (flake->WorkerIdBitLength <= 0)
|
||||
{
|
||||
perror("WorkerIdBitLength error.(range:[1, 21])");
|
||||
exit(1);
|
||||
}
|
||||
if (flake->SeqBitLength + flake->WorkerIdBitLength > 22)
|
||||
{
|
||||
perror("error:WorkerIdBitLength + SeqBitLength <= 22");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength;
|
||||
}
|
||||
// 2.WorkerIdBitLength
|
||||
if (flake->WorkerIdBitLength <= 0)
|
||||
{
|
||||
perror("WorkerIdBitLength error.(range:[1, 21])");
|
||||
exit(1);
|
||||
}
|
||||
if (flake->SeqBitLength + flake->WorkerIdBitLength > 22)
|
||||
{
|
||||
perror("error:WorkerIdBitLength + SeqBitLength <= 22");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength;
|
||||
}
|
||||
|
||||
// 3.WorkerId
|
||||
uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1;
|
||||
if (maxWorkerIdNumber == 0)
|
||||
{
|
||||
maxWorkerIdNumber = 63;
|
||||
}
|
||||
if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber)
|
||||
{
|
||||
perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}");
|
||||
exit(1);
|
||||
}
|
||||
// 3.WorkerId
|
||||
uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1;
|
||||
if (maxWorkerIdNumber == 0)
|
||||
{
|
||||
maxWorkerIdNumber = 63;
|
||||
}
|
||||
if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber)
|
||||
{
|
||||
perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 4.SeqBitLength
|
||||
if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21)
|
||||
{
|
||||
perror("SeqBitLength error. (range:[2, 21])");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength;
|
||||
}
|
||||
// 4.SeqBitLength
|
||||
if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21)
|
||||
{
|
||||
perror("SeqBitLength error. (range:[2, 21])");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength;
|
||||
}
|
||||
|
||||
// 5.MaxSeqNumber
|
||||
uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1;
|
||||
if (maxSeqNumber == 0)
|
||||
{
|
||||
maxSeqNumber = 63;
|
||||
}
|
||||
if (flake->MaxSeqNumber > maxSeqNumber)
|
||||
{
|
||||
perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber;
|
||||
}
|
||||
// 5.MaxSeqNumber
|
||||
uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1;
|
||||
if (maxSeqNumber == 0)
|
||||
{
|
||||
maxSeqNumber = 63;
|
||||
}
|
||||
if (flake->MaxSeqNumber > maxSeqNumber)
|
||||
{
|
||||
perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber;
|
||||
}
|
||||
|
||||
// 6.MinSeqNumber
|
||||
if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber)
|
||||
{
|
||||
perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber;
|
||||
}
|
||||
// 6.MinSeqNumber
|
||||
if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber)
|
||||
{
|
||||
perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber;
|
||||
}
|
||||
|
||||
// 7.Others
|
||||
flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount;
|
||||
flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->Method = flake->Method;
|
||||
// 7.Others
|
||||
flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount;
|
||||
flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->Method = flake->Method;
|
||||
}
|
||||
|
||||
// static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake)
|
||||
@@ -130,160 +132,169 @@ void Config(snowflake *flake)
|
||||
// }
|
||||
// }
|
||||
|
||||
static inline uint64_t NextOverCostId(snowflake *flake)
|
||||
static inline uint64_t NextOverCostId(snowflake* flake)
|
||||
{
|
||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake);
|
||||
if (currentTimeTick > flake->_LastTimeTick)
|
||||
{
|
||||
// EndOverCostAction(currentTimeTick, flake);
|
||||
flake->_LastTimeTick = currentTimeTick;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 0;
|
||||
flake->_OverCostCountInOneTerm = 0;
|
||||
// flake->_GenCountInOneTerm = 0;
|
||||
return CalcId(flake);
|
||||
}
|
||||
if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount)
|
||||
{
|
||||
// EndOverCostAction(currentTimeTick, flake);
|
||||
flake->_LastTimeTick = GetNextTimeTick(flake);
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 0;
|
||||
flake->_OverCostCountInOneTerm = 0;
|
||||
// flake->_GenCountInOneTerm = 0;
|
||||
return CalcId(flake);
|
||||
}
|
||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
|
||||
{
|
||||
flake->_LastTimeTick++;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 1;
|
||||
flake->_OverCostCountInOneTerm++;
|
||||
// flake->_GenCountInOneTerm++;
|
||||
return CalcId(flake);
|
||||
}
|
||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake);
|
||||
if (currentTimeTick > flake->_LastTimeTick)
|
||||
{
|
||||
// EndOverCostAction(currentTimeTick, flake);
|
||||
flake->_LastTimeTick = currentTimeTick;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 0;
|
||||
flake->_OverCostCountInOneTerm = 0;
|
||||
// flake->_GenCountInOneTerm = 0;
|
||||
return CalcId(flake);
|
||||
}
|
||||
if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount)
|
||||
{
|
||||
// EndOverCostAction(currentTimeTick, flake);
|
||||
flake->_LastTimeTick = GetNextTimeTick(flake);
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 0;
|
||||
flake->_OverCostCountInOneTerm = 0;
|
||||
// flake->_GenCountInOneTerm = 0;
|
||||
return CalcId(flake);
|
||||
}
|
||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
|
||||
{
|
||||
flake->_LastTimeTick++;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 1;
|
||||
flake->_OverCostCountInOneTerm++;
|
||||
// flake->_GenCountInOneTerm++;
|
||||
return CalcId(flake);
|
||||
}
|
||||
|
||||
// flake->_GenCountInOneTerm++;
|
||||
return CalcId(flake);
|
||||
// flake->_GenCountInOneTerm++;
|
||||
return CalcId(flake);
|
||||
}
|
||||
|
||||
static inline uint64_t NextNormalId(snowflake *flake)
|
||||
static inline uint64_t NextNormalId(snowflake* flake)
|
||||
{
|
||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake);
|
||||
if (currentTimeTick < flake->_LastTimeTick)
|
||||
{
|
||||
if (flake->_TurnBackTimeTick < 1)
|
||||
{
|
||||
flake->_TurnBackTimeTick = flake->_LastTimeTick - 1;
|
||||
flake->_TurnBackIndex++;
|
||||
if (flake->_TurnBackIndex > 4)
|
||||
{
|
||||
flake->_TurnBackIndex = 1;
|
||||
}
|
||||
}
|
||||
return CalcTurnBackId(flake);
|
||||
}
|
||||
if (flake->_TurnBackTimeTick > 0)
|
||||
{
|
||||
flake->_TurnBackTimeTick = 0;
|
||||
}
|
||||
if (currentTimeTick > flake->_LastTimeTick)
|
||||
{
|
||||
flake->_LastTimeTick = currentTimeTick;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
return CalcId(flake);
|
||||
}
|
||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
|
||||
{
|
||||
// flake->_TermIndex++;
|
||||
flake->_LastTimeTick++;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 1;
|
||||
flake->_OverCostCountInOneTerm = 1;
|
||||
// flake->_GenCountInOneTerm = 1;
|
||||
return CalcId(flake);
|
||||
}
|
||||
return CalcId(flake);
|
||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake);
|
||||
if (currentTimeTick < flake->_LastTimeTick)
|
||||
{
|
||||
if (flake->_TurnBackTimeTick < 1)
|
||||
{
|
||||
flake->_TurnBackTimeTick = flake->_LastTimeTick - 1;
|
||||
flake->_TurnBackIndex++;
|
||||
if (flake->_TurnBackIndex > 4)
|
||||
{
|
||||
flake->_TurnBackIndex = 1;
|
||||
}
|
||||
}
|
||||
return CalcTurnBackId(flake);
|
||||
}
|
||||
if (flake->_TurnBackTimeTick > 0)
|
||||
{
|
||||
flake->_TurnBackTimeTick = 0;
|
||||
}
|
||||
if (currentTimeTick > flake->_LastTimeTick)
|
||||
{
|
||||
flake->_LastTimeTick = currentTimeTick;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
return CalcId(flake);
|
||||
}
|
||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
|
||||
{
|
||||
// flake->_TermIndex++;
|
||||
flake->_LastTimeTick++;
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
flake->_IsOverCost = 1;
|
||||
flake->_OverCostCountInOneTerm = 1;
|
||||
// flake->_GenCountInOneTerm = 1;
|
||||
return CalcId(flake);
|
||||
}
|
||||
return CalcId(flake);
|
||||
}
|
||||
|
||||
static inline uint64_t GetCurrentTime()
|
||||
static inline uint64_t GetSysCurrentTime()
|
||||
{
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000);
|
||||
#ifdef WIN32
|
||||
FILETIME file_time;
|
||||
GetSystemTimeAsFileTime(&file_time);
|
||||
uint64_t time = ((uint64_t)file_time.dwLowDateTime) + ((uint64_t)file_time.dwHighDateTime << 32);
|
||||
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
|
||||
return (uint64_t)((time - EPOCH) / 10000LL);
|
||||
#else
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static inline uint64_t GetCurrentTimeTick(snowflake *flake)
|
||||
static inline uint64_t GetCurrentTimeTick(snowflake* flake)
|
||||
{
|
||||
return GetCurrentTime() - flake->BaseTime;
|
||||
return GetSysCurrentTime() - flake->BaseTime;
|
||||
}
|
||||
|
||||
static inline uint64_t GetNextTimeTick(snowflake *flake)
|
||||
static inline uint64_t GetNextTimeTick(snowflake* flake)
|
||||
{
|
||||
uint64_t tempTimeTicker = GetCurrentTimeTick(flake);
|
||||
while (tempTimeTicker <= flake->_LastTimeTick)
|
||||
{
|
||||
tempTimeTicker = GetCurrentTimeTick(flake);
|
||||
}
|
||||
return tempTimeTicker;
|
||||
uint64_t tempTimeTicker = GetCurrentTimeTick(flake);
|
||||
while (tempTimeTicker <= flake->_LastTimeTick)
|
||||
{
|
||||
tempTimeTicker = GetCurrentTimeTick(flake);
|
||||
}
|
||||
return tempTimeTicker;
|
||||
}
|
||||
|
||||
static inline uint64_t CalcId(snowflake *flake)
|
||||
static inline uint64_t CalcId(snowflake* flake)
|
||||
{
|
||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber);
|
||||
flake->_CurrentSeqNumber++;
|
||||
return result;
|
||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber);
|
||||
flake->_CurrentSeqNumber++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline uint64_t CalcTurnBackId(snowflake *flake)
|
||||
static inline uint64_t CalcTurnBackId(snowflake* flake)
|
||||
{
|
||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick);
|
||||
flake->_TurnBackTimeTick--;
|
||||
return result;
|
||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick);
|
||||
flake->_TurnBackTimeTick--;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline uint64_t NextSonwId(snowflake *flake)
|
||||
static inline uint64_t NextSonwId(snowflake* flake)
|
||||
{
|
||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake);
|
||||
if (flake->_LastTimeTick == currentTimeTick)
|
||||
{
|
||||
flake->_CurrentSeqNumber++;
|
||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
|
||||
{
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
currentTimeTick = GetNextTimeTick(flake);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
}
|
||||
flake->_LastTimeTick = currentTimeTick;
|
||||
return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber);
|
||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake);
|
||||
if (flake->_LastTimeTick == currentTimeTick)
|
||||
{
|
||||
flake->_CurrentSeqNumber++;
|
||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
|
||||
{
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
currentTimeTick = GetNextTimeTick(flake);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flake->_CurrentSeqNumber = flake->MinSeqNumber;
|
||||
}
|
||||
flake->_LastTimeTick = currentTimeTick;
|
||||
return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber);
|
||||
}
|
||||
|
||||
static inline uint64_t GetId(snowflake *flake)
|
||||
static inline uint64_t GetId(snowflake* flake)
|
||||
{
|
||||
return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake);
|
||||
return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake);
|
||||
}
|
||||
|
||||
uint64_t NextId(snowflake *flake)
|
||||
uint64_t NextId(snowflake* flake)
|
||||
{
|
||||
spin_lock(&flake->_Lock, pid);
|
||||
uint64_t id = GetId(flake);
|
||||
spin_unlock(&flake->_Lock, pid);
|
||||
return id;
|
||||
spin_lock(&flake->_Lock, pid);
|
||||
uint64_t id = GetId(flake);
|
||||
spin_unlock(&flake->_Lock, pid);
|
||||
return id;
|
||||
}
|
||||
|
||||
uint64_t *NextNumId(snowflake *flake, uint32_t num)
|
||||
uint64_t* NextNumId(snowflake* flake, uint32_t num)
|
||||
{
|
||||
uint64_t *arr = (uint64_t *)malloc(sizeof(uint64_t) * num);
|
||||
spin_lock(&flake->_Lock, pid);
|
||||
uint32_t i;
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
arr[i] = GetId(flake);
|
||||
}
|
||||
spin_unlock(&flake->_Lock, pid);
|
||||
return arr;
|
||||
uint64_t* arr = (uint64_t*)malloc(sizeof(uint64_t) * num);
|
||||
spin_lock(&flake->_Lock, pid);
|
||||
uint32_t i;
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
arr[i] = GetId(flake);
|
||||
}
|
||||
spin_unlock(&flake->_Lock, pid);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -1,47 +1,73 @@
|
||||
#include <stdlib.h>
|
||||
#ifdef WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include "spinlock.h"
|
||||
|
||||
extern int ncpu;
|
||||
extern int spin;
|
||||
|
||||
void spin_lock(atomic_t *lock, uint32_t pid)
|
||||
void spin_lock(atomic_t* lock, uint32_t pid)
|
||||
{
|
||||
int i, n;
|
||||
int i, n;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
|
||||
if (*lock == 0 &&
|
||||
__sync_bool_compare_and_swap(lock, 0, pid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (*lock == 0 &&
|
||||
#ifdef WIN32
|
||||
InterlockedCompareExchange(lock, pid, 0) == 0
|
||||
#else
|
||||
__sync_bool_compare_and_swap(lock, 0, pid)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncpu > 1)
|
||||
{
|
||||
if (ncpu > 1)
|
||||
{
|
||||
|
||||
for (n = 1; n < spin; n <<= 1)
|
||||
{
|
||||
for (n = 1; n < spin; n <<= 1)
|
||||
{
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
__asm("pause");
|
||||
}
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WIN32
|
||||
MemoryBarrier();
|
||||
#else
|
||||
__asm("pause");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (*lock == 0 &&
|
||||
__sync_bool_compare_and_swap(lock, 0, pid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sched_yield();
|
||||
}
|
||||
if (*lock == 0 &&
|
||||
#ifdef WIN32
|
||||
InterlockedCompareExchange(lock, pid, 0) == 0
|
||||
#else
|
||||
__sync_bool_compare_and_swap(lock, 0, pid)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
SwitchToThread();
|
||||
#else
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void spin_unlock(atomic_t *lock, uint32_t pid)
|
||||
void spin_unlock(atomic_t* lock, uint32_t pid)
|
||||
{
|
||||
__sync_bool_compare_and_swap(lock, pid, 0);
|
||||
#ifdef WIN32
|
||||
InterlockedCompareExchange(lock, 0, pid);
|
||||
#else
|
||||
__sync_bool_compare_and_swap(lock, pid, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user