Files
mir_server/sdk/utils/Tick.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

118 lines
3.3 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <limits.h>
#ifdef WIN32
#include <time.h>
#include <tchar.h>
#endif
#include "_osdef.h"
#include "Tick.h"
#include "Lock.h"
using namespace wylib::time::tick64;
static TICKCOUNT64 UserSetTick = 0;
#ifndef WIN32
unsigned int timeGetTime()
{
unsigned int uptime = 0;
struct timespec on;
if(clock_gettime(CLOCK_MONOTONIC, &on) == 0)
uptime = on.tv_sec*1000 + on.tv_nsec/1000000;
return uptime;
}
#endif
/***
实际测试的性能表明基于timeGetTime实现的GetTickCount64具有较高的性能
而基于QueryPerformanceCounter的实现则是timeGetTime版本时间消耗的300倍
***/
//static LONG dwAtomLock = 0;
#ifdef WIN32
static MMRESULT mmPeriod = timeBeginPeriod(1);
#endif
static TICKCOUNT64 llTickBase = 0;
static TICKCOUNT64 llStartTick = timeGetTime();
static DWORD dwLastShortTick = timeGetTime();
TICKCOUNT64 wylib::time::tick64::GetTickCount64()
{
if (UserSetTick)
return UserSetTick;
/*
此处需要将dwLastShortTick导致保存为局部变量并尝试通过保存的值以锁总线的方式改变dwLastShortTick的值。
由于在检测并修改dwLastShortTick的值的期间当前线程可能由于进程调度而使得线程被挂起。当前线程被挂
起的期间如果其他线程也执行了此函数则该线程会先于此线程修改dwLastShortTick的值。当本线程在恢复后再修改
dwLastShortTick的值将导致错误的结果并会错误的判断为进入了一个49天的循环并修改llTickBase的值从而导
致所有后续调用的返回值全部错误的问题!
为尽量降低数据同步的开销,不能使用临界区等方式来同步数据,故必须使用原子加锁操作指令代替。
*/
DWORD dwLastTick = dwLastShortTick;
DWORD dwTick = timeGetTime();
#ifdef WIN32
if (InterlockedCompareExchange((volatile long*)&dwLastShortTick, (long)dwTick, (long)dwLastTick) == dwLastTick)
#else
if (__sync_val_compare_and_swap((volatile long*)&dwLastShortTick, (long)dwLastTick, (long)dwTick) == dwLastTick)
#endif
{
if (dwTick < dwLastTick)
{
#ifdef WIN32
if (IsDebuggerPresent())
{
//请手动确认此处是否未发生BUG而是系统真正的经过了49天的循环并按继续键……
OutputDebugString(_T("请手动确认此处是否未发生BUG而是系统真正的经过了49天的循环"));
DebugBreak();
}
llTickBase += 0x1UI64 << 32;
#else
llTickBase += 0x1LL << 32;
#endif
}
}
return llTickBase + dwTick - llStartTick;
}
/*
TICKCOUNT64 wylib::time::tick64::GetTickCount64()
{
if (UserSetTick)
return UserSetTick;
static LARGE_INTEGER Frequency;
static BOOL boSuportPerformanceTick = QueryPerformanceFrequency(&Frequency);
LARGE_INTEGER tick;
TICKCOUNT64 sec, milpart;
if ( !boSuportPerformanceTick )
{
return timeGetTime();
}
QueryPerformanceCounter( &tick );
sec = tick.QuadPart / Frequency.QuadPart;
milpart = tick.QuadPart - (sec * Frequency.QuadPart);
return sec * 1000 + milpart * 1000 / Frequency.QuadPart;
}
*/
TICKCOUNT64 wylib::time::tick64::SetTickCount64(TICKCOUNT64 llValue)
{
//TICKCOUNT64 lOldTick = UserSetTick;
UserSetTick = llValue;
return UserSetTick;
}
TICKCOUNT32 wylib::time::tick64::GetTickCount32()
{
return timeGetTime();
}
TICKCOUNT32 wylib::time::tick64::SetTickCount32(TICKCOUNT32 dwTick)
{
return (TICKCOUNT32)SetTickCount64(dwTick);
}