#pragma once

namespace FDK
{
	public ref class CDisposed
	{
	public:
		CDisposed()
		{
			this->_bDisposed中または完了済みである = gcnew CAtom<bool>( false );
			this->_n現在Dispose中のスレッドのID = gcnew CAtom<int>( -1 );
		}

		// 成功すれば true を返す。
		bool t開始を宣言する()
		{
			if( this->_bDisposed中または完了済みである->Get() )
				return false;		// Dispose() は複数回呼び出される可能性があるので、例外は出さない。

			if( this->_n現在Dispose中のスレッドのID->Get() >= 0 )
				return false;
				
			this->_bDisposed中または完了済みである->Set( true );
			this->_n現在Dispose中のスレッドのID->Set( Thread::CurrentThread->ManagedThreadId );

			return true;
		}
		
		// 開始を宣言したスレッドの場合は例外は発生しない。
		void tDispose済みまたは実行中なら例外発生( String^ objectName )
		{
			if( this->_bDisposed中または完了済みである->Get() )
			{
				if( this->_n現在Dispose中のスレッドのID->Get() == Thread::CurrentThread->ManagedThreadId )
					return;		// 開始を宣言したスレッドならば、Dispose中でも例外を発生させない。

				throw gcnew ObjectDisposedException( objectName );	// Dispose中または完了済みなら例外発生。
			}
		}
		
		property bool bDispose済みまたは処理中である
		{
			bool get()
			{
				return this->_bDisposed中または完了済みである->Get();
			}
		}

	private:
		CAtom<bool>^ _bDisposed中または完了済みである;
		CAtom<int>^ _n現在Dispose中のスレッドのID;
	};
}
