/*---------------------------------------------------------------------------* Project: Horizon File: os_LightEvent.h 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: 12449 $ *---------------------------------------------------------------------------*/ #ifndef NN_OS_OS_LIGHTEVENT_H_ #define NN_OS_OS_LIGHTEVENT_H_ #ifdef __cplusplus #include #include #include #include namespace nn { namespace os { /*! @file @brief LightEvent に関するAPI の宣言 :include nn/os.h */ /*!--------------------------------------------------------------------------* @brief スレッド間でフラグの通知を行う同期機構です。 内部にフラグを持ち、このフラグをスレッド間で安全に操作したり、 また、フラグがセットされるのを待ち合わせたりすることができます。 複数の同期オブジェクトを同時に待つことができないという点を除いて nn::os::LightEvent の方が nn::os::Event より 優れているため、通常は nn::os::LightEvent を使用すべきです。 このクラスの初期化/終了以外のメンバ関数はスレッドセーフです。 *---------------------------------------------------------------------------*/ class LightEvent { private: static const s32 SIGNALED_MANUAL = 1; static const s32 SIGNALED_AUTO = 0; static const s32 NOT_SIGNALED_AUTO = -1; static const s32 NOT_SIGNALED_MANUAL = -2; private: WaitableCounter m_Counter; public: //---------------------------------------- //! @name 初期化/終了 //@{ /*!--------------------------------------------------------------------------* @brief コンストラクタです。 初期化を行わないコンストラクタです。 別途 @ref Initialize を呼び出す必要があります。 @return なし。 *---------------------------------------------------------------------------*/ LightEvent(){} /*!--------------------------------------------------------------------------* @brief コンストラクタです。 初期化を行うコンストラクタです。 別途 @ref Initialize を呼び出す必要はありません。 自動リセットでは、いずれかのスレッドが フラグがセットされることによって起床した場合、 フラグがクリアされます。 このため、複数のスレッドが待機していても一回のフラグのセットでは 一つのスレッドだけが起床します。 手動リセットではフラグが自動的にクリアされることはありません。 そのため、複数のスレッドが待機しているなら一回のフラグのセットで 全てのスレッドが起床します。 @param[in] isManualReset 手動リセットなら true、 自動リセットなら false を指定します。 @return なし。 *---------------------------------------------------------------------------*/ LightEvent(bool isManualReset) { Initialize(isManualReset); } /*!--------------------------------------------------------------------------* @brief 初期化を行います。 @param[in] isManualReset 手動リセットなら true、 自動リセットなら false を指定します。 @return なし。 *---------------------------------------------------------------------------*/ void Initialize(bool isManualReset) { *m_Counter = isManualReset ? NOT_SIGNALED_MANUAL: NOT_SIGNALED_AUTO; } /*!--------------------------------------------------------------------------* @brief 終了処理を行います。 @return なし。 *---------------------------------------------------------------------------*/ void Finalize() {} //@} //---------------------------------------- //! @name デバッグ用情報取得 //@{ /*!--------------------------------------------------------------------------* @brief フラグがセットされているかどうかを取得します。 この関数は主にデバッグ用です。 通常は @ref TryWait を用いてください。 この関数は自動リセットか手動リセットかによらず 単純にフラグがセットされているかどうかを取得します。 フラグの状態を変更することはしません。 @return フラグがセットされているなら true、 そうでなければ false を返します。 *---------------------------------------------------------------------------*/ bool IsSignaled() const { return *m_Counter >= 0; } /*!--------------------------------------------------------------------------* @brief 手動リセットかどうかを取得します。 @return 手動リセットなら true、 そうでなければ false を返します。 *---------------------------------------------------------------------------*/ bool IsManualReset() const { const s32 c = *m_Counter; return (c == SIGNALED_MANUAL) || (c == NOT_SIGNALED_MANUAL); } //@} //---------------------------------------- //! @name フラグの操作と待ち合わせ //@{ /*!--------------------------------------------------------------------------* @brief フラグがセットされているかどうかを取得します。 自動リセットの場合、フラグがセットされているなら フラグのクリアも行います。 @return フラグがセットされていたなら true、 そうでなければ false を返します。 *---------------------------------------------------------------------------*/ bool TryWait(); /*!--------------------------------------------------------------------------* @brief フラグがセットされるまで待機します。 自動リセットの場合は、フラグがセットされ待機が解除されると 同時にフラグをクリアします。 @return なし。 *---------------------------------------------------------------------------*/ void Wait(); /*!--------------------------------------------------------------------------* @brief フラグをセットします。 フラグがセットされるのを待機しているスレッドが存在するなら そのスレッドを起床させます。 自動リセットの場合、複数のスレッドが待機していても 起床するスレッドは 1 つだけです。 起床するスレッドはスレッド優先度が高い方から優先的に起床します。 また、待機しているスレッドが存在するなら、 そのスレッドが起床すると同時にフラグがクリアされます。 待機しているスレッドが存在しなければ フラグはセットされたままになります。 手動リセットの場合、全ての待機しているスレッドが起床します。 またフラグはセットされたままになります。 @return なし。 *---------------------------------------------------------------------------*/ void Signal(); /*!--------------------------------------------------------------------------* @brief フラグがセットされるのを待機しているスレッドを解放します。 自動リセットの場合は待機しているスレッドのうち 最もスレッド優先度が高いスレッドを一つだけ起床させ、 その後フラグをクリアします。 待機しているスレッドが存在しなくてもフラグをクリアする点が Signal と異なります。 手動リセットの場合は待機している全てのスレッドを起床させ、 その後フラグをクリアします。 @return なし。 *---------------------------------------------------------------------------*/ void Pulse(); /*!--------------------------------------------------------------------------* @brief フラグをクリアします。 @return なし。 *---------------------------------------------------------------------------*/ void ClearSignal(); //@} }; }} // namespace nn::os #endif // __cplusplus // 以下、C 用宣言 #include /*! @addtogroup nn_os @{ @defgroup nn_os_LightEvent_c LightEvent (C) @brief @ref nn::os::LightEvent の C インタフェースモジュールです。 @{ */ /*! @struct nnosLightEvent @brief ライトイベントを表す C の構造体です。 @brief 対応するクラス @ref nn::os::LightEvent を参照してください。 */ NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosLightEvent, nn::os::LightEvent, 4, u32); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::Initialize を参照してください。 */ NN_EXTERN_C void nnosLightEventInitialize(nnosLightEvent* this_, bool isManualReset); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::IsSignaled を参照してください。 */ NN_EXTERN_C bool nnosLightEventIsSignaled(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::IsManualReset を参照してください。 */ NN_EXTERN_C bool nnosLightEventIsManualReset(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::TryWait を参照してください。 */ NN_EXTERN_C bool nnosLightEventTryWait(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::Wait を参照してください。 */ NN_EXTERN_C void nnosLightEventWait(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::Signal を参照してください。 */ NN_EXTERN_C void nnosLightEventSignal(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::Pulse を参照してください。 */ NN_EXTERN_C void nnosLightEventPulse(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::ClearSignal を参照してください。 */ NN_EXTERN_C void nnosLightEventClearSignal(nnosLightEvent* this_); /*! @brief 対応する C++ 関数 @ref nn::os::LightEvent::Finalize を参照してください。 */ NN_EXTERN_C void nnosLightEventFinalize(nnosLightEvent* this_); /*! @} @} */ #endif // ifndef NN_OS_OS_LIGHTEVENT_H_