Chinaunix首页 | 论坛 | 博客
  • 博客访问: 845939
  • 博文数量: 756
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:40
文章分类

全部博文(756)

文章存档

2011年(1)

2008年(755)

我的朋友

分类:

2008-10-13 16:09:07

#include 
#include 
#include 

int main(int argc, char* argv[])
{
  SYSTEMTIME st;
  while (true)
  {
    ::GetSystemTime(&st);
    std::cout << std::setw(2) << st.wHour << ':'
              << std::setw(2) << st.wMinute << ':'
              << std::setw(2) << st.wSecond << '.'
              << std::setw(3) << st.wMilliseconds << '\n';
  }

  return 0;
}

#include 
#include 
#include 

struct reference_point
{
	FILETIME file_time;
	LARGE_INTEGER counter;
};

void simplistic_synchronize(reference_point& ref_point)
{
	FILETIME  	ft0 = {0, 0},
			ft1 = {0, 0};
	LARGE_INTEGER   li;

	//
	// Spin waiting for a change in system time. Get the matching
	// performace counter value for that time.
	//
	::GetSystemTimeAsFileTime(&ft0);
	do
	{
		::GetSystemTimeAsFileTime(&ft1);
		::QueryPerformanceCounter(&li);
	}
	while((ft0.dwHighDateTime == ft1.dwHighDateTime) &&
		  (ft0.dwLowDateTime == ft1.dwLowDateTime));

	ref_point.file_time = ft1;
	ref_point.counter = li;
}

void get_time(LARGE_INTEGER frequency, const reference_point&
	reference, FILETIME& current_time)
{
	LARGE_INTEGER li;

	::QueryPerformanceCounter(&li);

	//
	// Calculate performance counter ticks elapsed
	//
	LARGE_INTEGER ticks_elapsed;

	ticks_elapsed.QuadPart = li.QuadPart -
		reference.counter.QuadPart;

	//
	// Translate to 100-nanosecondsintervals (FILETIME
	// resolution) and add to
	// reference FILETIME to get current FILETIME.
	//
	ULARGE_INTEGER filetime_ticks,
		       filetime_ref_as_ul;

	filetime_ticks.QuadPart =
		(ULONGLONG)((((double)ticks_elapsed.QuadPart/(double)
		frequency.QuadPart)*10000000.0)+0.5);
	filetime_ref_as_ul.HighPart = reference.file_time.dwHighDateTime;
	filetime_ref_as_ul.LowPart = reference.file_time.dwLowDateTime;
	filetime_ref_as_ul.QuadPart += filetime_ticks.QuadPart;

	//
	// Copy to result
	//
	current_time.dwHighDateTime = filetime_ref_as_ul.HighPart;
	current_time.dwLowDateTime = filetime_ref_as_ul.LowPart;
}

int main(int argc, char* argv[])
{
	reference_point ref_point;
	LARGE_INTEGER	frequency;
	FILETIME	file_time;
	SYSTEMTIME	system_time;
		
	::QueryPerformanceFrequency(&frequency);	
	simplistic_synchronize(ref_point);
	while (true)
	{			
		get_time(frequency, ref_point, file_time);
		::FileTimeToSystemTime(&file_time, &system_time);
		std::cout << std::setw(2) << system_time.wHour << ':'
			  << std::setw(2) << system_time.wMinute << ':'
			  << std::setw(2) << system_time.wSecond << ':'
			  << std::setw(3) << system_time.wMilliseconds << '\n';
	}

	return 0;
}

模板参数
counter_type 代表高精度,高频率的计数器。它必须提供静态成员值和频率,同value_type定义一样。
KEEP_WITHIN_MICROS 定义时间供应器最大可以偏离实际系统时间的微秒个数。它也影响再同步线程的同步频率。
SYNCHRONIZE_THREAD_PRIORITY 定义同步线程在执行同步时应该设置的自身优先级。这个不应该被修改除非你的程序不断的在一个高优先级上执行。缺省的是THREAD_PRIORITY_BELOW_NORMAL,这样不会打扰正常或高优先级线程的正常执行。
TUNING_LIMIT_PARTSPERBILLION 当前时间供应器的实现是连续的测量计数器频率。这个频率在内部被维护,允许较少频率的再同步和更准确的定时。当测量的频率的精确度达到一定阈值时,就不会再执行调整(但周期性再同步总是活动的)。这个极限的单位是计算频率的错误比率,对应的缺省值是每10亿100单位。
MAX_WAIT_MILLIS 定义允许的最大调谐间隔,毫秒为单位——也就是,检查高精度时间偏离系统时间有多远前的等待时间。调谐间隔是自动调整的,但只能达到这个极限。这个参数一般不应该被修改。
MIN_WAIT_MILLIS 定义最小允许的调谐间隔,毫秒为单位。细节见MAX_WAIT_MILLS
类型定义
raw_value_type 能够存储“原始”时戳的类型
成员函数
instance 返回这个类的唯一实例的引用
systemtime返回当前的系统时间,格式是SYSTEMTIME结构
filetime 返回当前系统时间,格式是FILETIME结构
rawtime 返回当前系统时间,用最小的负荷返回“原始”时戳。为了把它转为绝对时间使用filetime_from_rawtime或者systemtime_from_rawtime
systemtime_from_rawtime 把“原始”时戳转为绝对时间,用SYSTEMTIME结构表示
filetime_from_rawtime 把“原始”时戳转为绝对时间,用FILETIME结构表示



#include 
#include 
#include 
#include 
#include 
#include 

using namespace hrt;

typedef time_provider  time_provider_type;
typedef time_provider_type::raw_value_type  raw_time_type;
typedef std::vector          raw_vector;

const int NUMBER_OF_SAMPLES = 1000;

int main(int argc, char* argv[])
{
  raw_vector          samples;
  time_provider_type& provider = time_provider_type::instance();

  samples.reserve(NUMBER_OF_SAMPLES);

  for (int i = 0; i < NUMBER_OF_SAMPLES; ++i)
  {
    samples.push_back(provider.rawtime());
  }

  system_time st;

  for (raw_vector::iterator iter = samples.begin(); 
       iter != samples.end(); ++iter)
  {
    provider.systemtime_from_rawtime(*iter, st.pointer());
    std::cout << std::setfill('0')
              << std::setw(2) << st.hour() << ':'
              << std::setw(2) << st.minute() << ':'
              << std::setw(2) << st.second() << '.'
              << std::setw(3) << st.millis() << '\n';
  }

  return 0;
}


Win32 API 执行时间 time_provider 执行时间
GetSystemTimeAsFileTime 1.9% (~0%) filetime 135% (900%)
GetSystemTime 100% (100%) systemtime 234% (1001%)
QueryPerformanceCounter 55% (400%) rawtime 57% (400%)



  使用我在文中描述的同步方法,你可以指定你想要的结果精度。然而,实际上,你能得到的结果的质量有平台相关性(硬件和软件)限制。在 Windows NT 中时钟中断处理器需要花费时间来执行, 大大地限制了你的精度不可能优于时钟中断处理器的执行时间,加上线程上下文切换时间,还有当时间变化时调用函数进行检查所花的时间。如果你在对称多处理(SMP)机器上运行, 你可以通过在另一个 CPU 上运行同步线程来避免时钟中断问题。
  在 SMP 机器上禁止同步线程运行在处理时钟中断的 CPU 上可以产生数十倍差异的同步精度。唯一的问题是你要首先知道哪个 CPU 在处理实际的时钟中断。从我有限的经验来看我只能告诉你好像是CPU#0来处理(我 想这种感觉有些怪怪的)。假设这是真的,你可以仅仅使用 SetThreadAffinityMask API 从允许处理器的线程列表中移去 CPU#0。你应该 通过预先检查 GetProcessAffinityMask 的调用结果来确认该进程被允许在另一个处理器上运行。
--------------------next---------------------

阅读(304) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~