using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace FDK.同期
{
///
/// ON, OFF, 無効 の3状態を持つイベント。
///
///
/// 状態が 無効 にされると、ON待ち/OFF待ちスレッドのブロックはいずれも解除され、
/// またそれ以降、状態を変更することはできなくなる(リセットすると戻る)。
///
public class TriStateEvent
{
public enum 状態種別 { ON, OFF, 無効 }
public 状態種別 現在の状態
{
get
{
lock( this._スレッド間同期 )
{
return this._状態;
}
}
set
{
lock( this._スレッド間同期 )
{
if( this._状態 == 状態種別.無効 )
return; // 一度無効になったら、以降は変更不可。
this._状態 = value;
switch( value )
{
case 状態種別.ON:
this._無効イベント?.Reset();
this._OFFイベント?.Reset();
this._ONイベント?.Set();
break;
case 状態種別.OFF:
this._無効イベント?.Reset();
this._ONイベント?.Reset();
this._OFFイベント?.Set();
break;
case 状態種別.無効:
this._ONイベント?.Set();
this._OFFイベント?.Set();
this._無効イベント?.Set();
break;
}
}
}
}
public TriStateEvent( 状態種別 初期状態 = 状態種別.OFF )
{
this.リセットする( 初期状態 );
}
///
/// 状態が ON または 無効 になるまでブロックする。
///
///
/// 解除後の状態(ON または 無効)。
///
public 状態種別 ONになるまでブロックする()
{
int h = EventWaitHandle.WaitAny( new EventWaitHandle[] { this._ONイベント, this._無効イベント } );
return ( h == 0 ) ? 状態種別.ON : 状態種別.無効;
}
///
/// 状態が OFF または 無効 になるまでブロックする。
///
///
/// 解除後の状態(OFF または 無効)。
///
public 状態種別 OFFになるまでブロックする()
{
int h = EventWaitHandle.WaitAny( new EventWaitHandle[] { this._OFFイベント, this._無効イベント } );
return ( h == 0 ) ? 状態種別.OFF : 状態種別.無効;
}
///
/// 状態が 無効 になるまでブロックする。
///
public void 無効になるまでブロックする()
{
this._無効イベント.WaitOne();
}
///
/// 状態をリセットする。
/// すでに無効になった後でも可。
///
public void リセットする( 状態種別 初期状態 = 状態種別.OFF )
{
lock( this._スレッド間同期 )
{
this.現在の状態 = 初期状態;
this._無効イベント = new ManualResetEvent( false );
this._ONイベント = new ManualResetEvent( 初期状態 == 状態種別.ON );
this._OFFイベント = new ManualResetEvent( 初期状態 == 状態種別.OFF );
}
}
private 状態種別 _状態 = 状態種別.OFF;
private ManualResetEvent _無効イベント = null;
private ManualResetEvent _ONイベント = null;
private ManualResetEvent _OFFイベント = null;
private readonly object _スレッド間同期 = new object();
}
}