#region Using
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
#endregion
namespace Wankuma.Interop
{
///
/// QueryPerformanceCounter を使ったパフォーマンスカウンタです。
///
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public class InteropQueryPerformanceCounter
{
#region P/Invoke
///
/// P/Invokeネイティブメソッド
///
private sealed class NativeMethods
{
///
/// インスタンス化防止コンストラクタ
///
private NativeMethods()
{
}
///
/// 高分解能パフォーマンスカウンタが存在する場合、そのカウンタの現在の値を取得します。
///
/// 1 個の変数へのポインタを指定します。関数から制御が返ると、この変数に、高分解能パフォーマンスカウンタの現在の値が格納されます。インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この変数に 0 が格納されることがあります。
/// インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしている場合、0 以外の値が返ります。関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、GetLastError 関数を使います。たとえば、インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この関数は失敗します。
[DllImport("kernel32.dll")]
[SuppressUnmanagedCodeSecurity]
public extern static int QueryPerformanceCounter(ref long lpPerformanceCount);
///
/// 高分解能パフォーマンスカウンタが存在する場合、そのカウンタの周波数(更新頻度)を取得します。システムが動作している間は、周波数を変更できません。
///
/// 個の変数へのポインタを指定します。関数から制御が返ると、この変数に、高分解能パフォーマンスカウンタの周波数が格納されます。周波数は、1 秒あたりのカウント数として表現されます。インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この変数に 0 が格納されることがあります。
/// ハードウェアが高分解能パフォーマンスカウンタをサポートしている場合は、0 以外の値が返ります。関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、GetLastError 関数を使います。たとえば、インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この関数は失敗します。
[DllImport("kernel32.dll")]
[SuppressUnmanagedCodeSecurity]
public extern static int QueryPerformanceFrequency(ref long lpFrequency);
}
#endregion
#region メンバ
private long _StratTime = 0;
private long _EndTime = 0;
private long _Frequency = 0;
#endregion
#region public long Frequency
///
/// 分解能を取得します。
///
/// このシステムではQueryPerformanceCounterが対応していません。
public long Frequency
{
get
{
if (this._Frequency != 0 )
{
return this._Frequency;
}
else
{
if ( NativeMethods.QueryPerformanceFrequency(ref this._Frequency) == 0 )
{
throw new NotSupportedException("このシステムでは対応していません。");
}
else
{
return this._Frequency;
}
}
}
}
#endregion
#region public void Start()
///
/// 計測を開始します
///
/// このシステムではQueryPerformanceCounterが対応していません。
public void Start()
{
if ( NativeMethods.QueryPerformanceCounter(ref this._StratTime) == 0 )
{
throw new NotSupportedException("このシステムでは対応していません。");
}
}
#endregion
#region public void End()
///
/// 計測を終了します
///
/// このシステムではQueryPerformanceCounterが対応していません。
public void End()
{
if ( NativeMethods.QueryPerformanceCounter(ref this._EndTime) == 0 )
{
throw new NotSupportedException("このシステムでは対応していません。");
}
}
#endregion
#region public double Result
///
/// Start()で計測を開始し、End()までの計測結果を返します。
///
/// このシステムではQueryPerformanceCounterが対応していません。
public double Result
{
get
{
return (this._EndTime - this._StratTime) * 1.0f / (double)this.Frequency;
}
}
#endregion
#region public double NowResult
///
/// Start()で計測を開始し、現在時点での計測結果を返します
///
/// このシステムではQueryPerformanceCounterが対応していません。
public double NowResult
{
get
{
long NowTime = 0;
if ( NativeMethods.QueryPerformanceCounter(ref NowTime) == 0 )
{
throw new NotSupportedException("このシステムでは対応していません。");
}
return (NowTime - this._StratTime) * 1.0f / (double)this.Frequency;
}
}
#endregion
}
}