/*---------------------------------------------------------------------------* Project: Horizon File: os_Semaphore.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: 33844 $ *---------------------------------------------------------------------------*/ /*! @file @brief Semaphore に関するAPI の宣言 :include nn/os.h */ #ifndef NN_OS_OS_SEMAPHORE_H_ #define NN_OS_OS_SEMAPHORE_H_ #include #include #include #include #include #include #include #ifdef __cplusplus namespace nn { namespace os { /*! @brief セマフォを扱う為のクラスです。セマフォはカウンタを持つ同期オブジェクトです。 通常は @ref nn::os::Semaphore ではなく、@ref nn::os::LightSemaphore を使用すべきです。 複数の同期オブジェクトを待つことができない点を除いて @ref nn::os::Semaphore よりも @ref nn::os::LightSemaphore の方が優れています。 セマフォの Wait 動作では、セマフォカウンタが 0 より大きくなることを待った後、セマフォカウンタを 1 増やします。 セマフォカウンタが 0 のときは、Wait 動作は解放されません。 セマフォのカウンタを増やすには @ref Release を呼び出します。 同期オブジェクトについては、@ref nn::os::Event を参照してください。 Semaphore オブジェクトは 8個まで作成することが出来ます。 また、API によってはこの制限にカウントされるリソースを消費する場合がありますので、ご注意ください。 */ class Semaphore : public InterruptEvent { public: /*! @brief セマフォを構築し、初期化します。 初期化しないコンストラクタと、初期化するコンストラクタが用意されています。 初期化しないコンストラクタを使用した場合は、別途 @ref Initialize の呼び出しが必要です。 @param[in] initialCount 作成直後のセマフォのカウント値。 @param[in] maxCount このセマフォが取りうる最大カウント値。 */ Semaphore(s32 initialCount, s32 maxCount); /*! @brief セマフォを構築します。初期化はしません。使用する為には @ref Initialize の呼び出しが必要です。 */ Semaphore() {} /*! @brief 構築済みのセマフォを初期化します。 @param[in] initialCount 作成直後のセマフォのカウント値。 @param[in] maxCount このセマフォが取りうる最大カウント値。 @return 無し。 */ void Initialize(s32 initialCount, s32 maxCount); /*! @brief 構築済みのセマフォの初期化を試みます。 @param[in] initialCount 作成直後のセマフォのカウント値。 @param[in] maxCount このセマフォが取りうる最大カウント値。 @return 成功するとtrue、失敗するとfalseを返します。 */ nn::Result TryInitialize(s32 initialCount, s32 maxCount); /*! @brief セマフォを破棄します。 デストラクタからも自動で呼ばれます。 @return 無し。 */ void Finalize() { InterruptEvent::Finalize(); } /*! @brief デストラクタです。 */ ~Semaphore() {} /*! @brief セマフォの解放(V 操作)を行い、カウンタ値を増やします。 セマフォ待ちでブロックされているスレッドがある場合には、最も優先順位の高いスレッドの 1 つがブロックから解除されます。 @param[in] releaseCount カウント値の増分を指定します。 @return releaseCount を加える前のカウント値を返します。 */ s32 Release(s32 releaseCount = 1); /*! @brief セマフォの取得(P 操作)を行い、カウンタ値を 1 減らします。 @return 無し。 */ void Acquire() { this->WaitOne(); } /*! @brief セマフォの取得(P 操作)を試行します。 成功するとカウンタ値を 1 減らします。 @param[in] timeout タイムアウト時間を指定します。0 を指定すると即座に処理を返します。 @return タイムアウト時間内に取得が成功したかを返します。 */ bool TryAcquire(nn::fnd::TimeSpan timeout) { return this->WaitOne(timeout); } class ScopedLock; private: Result TryInitializeImpl(s32 initialCount, s32 maxCount); }; inline Result Semaphore::TryInitializeImpl(s32 initialCount, s32 maxCount) { Handle handle; NN_UTIL_RETURN_IF_FAILED(nn::svc::CreateSemaphore(&handle, initialCount, maxCount)); this->SetHandle(handle); return ResultSuccess(); } inline void Semaphore::Initialize(s32 initialCount, s32 maxCount) { NN_ERR_THROW_FATAL(TryInitializeImpl(initialCount, maxCount)); } inline nn::Result Semaphore::TryInitialize(s32 initialCount, s32 maxCount) { Result result = TryInitializeImpl(initialCount, maxCount); if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE) { return result; } NN_ERR_THROW_FATAL(result); return result; } inline Semaphore::Semaphore(s32 initialCount, s32 maxCount) { Initialize(initialCount, maxCount); } inline s32 Semaphore::Release(s32 releaseCount) { s32 ret; NN_ERR_THROW_FATAL(nn::svc::ReleaseSemaphore(&ret, GetHandle(), releaseCount)); return ret; } NN_UTIL_DETAIL_DEFINE_SCOPED_LOCK(Semaphore, Acquire(), Release()); }} // namespace nn::os #endif // __cplusplus // 以下、C 用宣言 #include /*! @addtogroup nn_os @{ @defgroup nn_os_Semaphore_c Semaphore (C) @brief @ref nn::os::Semaphore の C インタフェースモジュールです。 @{ */ /*! @struct nnosSemaphore @brief セマフォを表す C の構造体です。 @brief 対応するクラス @ref nn::os::Semaphore を参照してください。 */ NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosSemaphore, nn::os::Semaphore, 4, u32); NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosSemaphoreToWaitObject, nnosSemaphore, nnosWaitObject); NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosWaitObjectToSemaphore, nnosWaitObject, nnosSemaphore); /*! @brief 対応する C++ 関数 @ref nn::os::Semaphore::Semaphore を参照してください。 */ NN_EXTERN_C void nnosSemaphoreInitialize(nnosSemaphore* this_, s32 initialCount, s32 maxCount); /*! @brief 対応する C++ 関数 @ref nn::os::Semaphore::Semaphore を参照してください。 */ NN_EXTERN_C bool nnosSemaphoreTryInitialize(nnosSemaphore* this_, s32 initialCount, s32 maxCount); /*! @brief 対応する C++ 関数 @ref nn::os::Semaphore::Release を参照してください。 */ NN_EXTERN_C s32 nnosSemaphoreRelease(nnosSemaphore* this_, s32 releaseCount); /*! @brief 対応する C++ 関数 @ref nn::os::Semaphore::Acquire を参照してください。 */ NN_EXTERN_C void nnosSemaphoreAcquire(nnosSemaphore* this_); /*! @brief 対応する C++ 関数 @ref nn::os::Semaphore::TryAcquire を参照してください。 */ NN_EXTERN_C bool nnosSemaphoreTryAcquire(nnosSemaphore* this_, s64 nanoSeconds); /*! @brief 対応する C++ 関数 @ref nn::os::Semaphore::Finalize を参照してください。 */ NN_EXTERN_C void nnosSemaphoreFinalize(nnosSemaphore* this_); /*! @} @} */ #endif