/*---------------------------------------------------------------------------* Project: Horizon File: os_LightEvent.cpp Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 16480 $ *---------------------------------------------------------------------------*/ #include //--------------------------------------------------------------------------- namespace nn { namespace os { // フラグがセットされているかどうかを取得します。 bool LightEvent::TryWait() { if( *m_Counter == SIGNALED_MANUAL ) { // 手動リセットなのでフラグのリセットは行いません。 return true; } else { // フラグが設定されていれば、フラグをリセットして true を返します。 return m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO; } } // フラグがセットされるまで待機します。 void LightEvent::Wait() { for(;;) { switch( *m_Counter ) { // フラグがセットされるまで待機、フラグはクリアしません。 case NOT_SIGNALED_MANUAL: m_Counter.WaitIfLessThan(0); return; // フラグはセットされているので待機しません。 case SIGNALED_MANUAL: return; // フラグはセットされていないので待機します。 case NOT_SIGNALED_AUTO: break; // フラグはセットされているので待機しません。フラグはリセットします。 case SIGNALED_AUTO: { if( m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO ) { return; } } break; } // フラグがセットされるまで待機します // フラグがセットされれば m_Counter が NOT_SIGNALED_AUTO から SIGNALED_AUTO に変わります。 m_Counter.WaitIfLessThan(0); } } // フラグをセットします。 void LightEvent::Signal() { if( *m_Counter == NOT_SIGNALED_AUTO ) { *m_Counter = SIGNALED_AUTO; // 自動リセットの場合は、優先度の高いスレッドを起床します。 // スレッド起床と同時にフラグはリセットされます。 m_Counter.Signal(1); } else if( *m_Counter == NOT_SIGNALED_MANUAL ) { *m_Counter = SIGNALED_MANUAL; // 手動リセットの場合は、待機しているすべてのスレッドを起床します。 // スレッドが起床してもフラグはリセットされません。 m_Counter.SignalAll(); } // 待機しているスレッドが存在しなければフラグはそのままです。 } // フラグがセットされるのを待機しているスレッドを解放します。 void LightEvent::Pulse() { switch( *m_Counter ) { case SIGNALED_MANUAL: *m_Counter = NOT_SIGNALED_MANUAL; // not break case NOT_SIGNALED_MANUAL: // フラグのセットを待機しているすべてのスレッドを起床します。 // スレッド起床と同時にフラグはリセットされます。 m_Counter.SignalAll(); break; case NOT_SIGNALED_AUTO: // フラグのセットを待機しているスレッドのうち、 // 最も優先度の高いスレッドを起床します。 // スレッド起床と同時にフラグはリセットされます。 m_Counter.Signal(1); break; case SIGNALED_AUTO: // フラグをリセットします。 *m_Counter = NOT_SIGNALED_AUTO; break; } } // フラグをクリアします。 void LightEvent::ClearSignal() { if( *m_Counter == SIGNALED_MANUAL ) { *m_Counter = NOT_SIGNALED_MANUAL; } else if( *m_Counter == SIGNALED_AUTO ) { *m_Counter = NOT_SIGNALED_AUTO; } } } } using namespace nn; // C 関数の定義 #include using namespace nn::os; extern "C" { void nnosLightEventInitialize(nnosLightEvent* p, bool isManualReset) { new (p) LightEvent(isManualReset); } bool nnosLightEventIsSignaled(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); return pLightEvent->IsSignaled(); } bool nnosLightEventIsManualReset(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); return pLightEvent->IsManualReset(); } bool nnosLightEventTryWait(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); return pLightEvent->TryWait(); } void nnosLightEventWait(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Wait(); } void nnosLightEventSignal(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Signal(); } void nnosLightEventPulse(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Pulse(); } void nnosLightEventClearSignal(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->ClearSignal(); } void nnosLightEventFinalize(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Finalize(); pLightEvent->~LightEvent(); } } // extern "C"