/*---------------------------------------------------------------------------* Project: Horizon File: os_Synchronization.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: 16692 $ *---------------------------------------------------------------------------*/ /*! @file @brief Synchronization に関する API の宣言 :include nn/os.h */ #ifndef NN_OS_OS_SYNCHRONIZATION_H_ #define NN_OS_OS_SYNCHRONIZATION_H_ #include #include #include #include #include /*! @def NN_OS_WAIT_INFINITE @brief タイムアウトしないことを表します。 */ #define NN_OS_WAIT_INFINITE -1 #ifdef __cplusplus namespace nn{ namespace os{ const s64 WAIT_INFINITE = NN_OS_WAIT_INFINITE; /*! @brief Wait することができるオブジェクトの基底クラスです。 @ref WaitOne でインスタンスオブジェクトを Wait することができます。 @ref WaitAny や @ref WaitAll で、複数の WaitObject を同時に Wait することができます。 これらの Wait 動作は、オブジェクトの状態変化によって解放されますが、 Wait 動作の解放が何を表すかは継承したクラスによります。 継承先クラスでは、Wait 動作の具体的な名前を示す名前で、独自の関数が定義されていることがあります。 Wait 動作をしたスレッドは、Wait 動作が解放されるまでブロックされ、 CPU リソースを他のスレッドに明け渡します。 このクラスを直接インスタンス化することはできません。 継承先のクラスを使用してください。 */ class WaitObject : public HandleObject { public: /*! @brief インスタンスオブジェクト一つを待ちます。 @return 無し。 */ void WaitOne(); /*! @brief インスタンスオブジェクト一つをタイムアウトつきで待ちます。 @param[in] timeout タイムアウト時間を指定します。 @return falseが返ってきたら、タイムアウトしたことを表します。 */ bool WaitOne(nn::fnd::TimeSpan timeout); /*! @brief 全てのオブジェクトを待ちます。 @param[in] objs WaitObjectの配列を指定します。 @param[in] numObjects WaitObjectの数を指定します。 @return 無し。 */ static void WaitAll(WaitObject* objs[], s32 numObjects); /*! @brief 全てのオブジェクトをタイムアウトつきで待ちます。 @param[in] objs WaitObjectの配列を指定します。 @param[in] numObjects WaitObjectの数を指定します。 @param[in] timeout タイムアウト時間を指定します。 @return false が返ってきたら、タイムアウトしたことを表します。 */ static bool WaitAll(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout); // /*! @brief どれか一つのオブジェクトを待ちます。 @param[in] objs WaitObjectの配列を指定します。 @param[in] numObjects WaitObjectの数を指定します。 @return Wait 動作が解放されたオブジェクトの objs 配列中でのインデックスを返します。 */ static s32 WaitAny(WaitObject* objs[], s32 numObjects); /*! @brief どれか一つのオブジェクトをタイムアウトつきで待ちます。 @param[in] objs WaitObjectの配列を指定します。 @param[in] numObjects WaitObjectの数を指定します。 @param[in] timeout タイムアウト時間を指定します。 @return Wait 動作が解放されたオブジェクトの objs 配列中でのインデックスを返します。タイムアウトしたときには負の値が返ります。 */ static s32 WaitAny(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout); protected: // 単独インスタンス化の禁止 WaitObject() {} ~WaitObject() {} private: nn::Result WaitOneImpl(s64 nanoSecondsTimeout); static nn::Result WaitMultiple(s32* pOut, WaitObject* objs[], s32 numObjects, bool waitAll, s64 nanoSecondsTimeout); }; /*! @brief ライブラリが内部で使うための抽象クラスです。 直接使わないようにしてください。 */ class InterruptEvent : public WaitObject { protected: InterruptEvent() {} ~InterruptEvent() {} }; // インライン実装 inline nn::Result WaitObject::WaitOneImpl(s64 nanoSecondsTimeout) { s32 dummy; Handle handle = GetHandle(); return nn::svc::WaitSynchronization(&dummy, &handle, 1, false, nanoSecondsTimeout); } inline void WaitObject::WaitOne() { NN_UTIL_PANIC_IF_FAILED(WaitOneImpl(WAIT_INFINITE)); } inline bool WaitObject::WaitOne(nn::fnd::TimeSpan timeout) { nn::Result result = WaitOneImpl(timeout.GetNanoSeconds()); NN_UTIL_PANIC_IF_FAILED(result); return result.GetDescription() != nn::Result::DESCRIPTION_TIMEOUT; } inline bool WaitObject::WaitAll(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout) { s32 dummy; nn::Result result = WaitMultiple(&dummy, objs, numObjects, true, timeout.GetNanoSeconds()); NN_UTIL_PANIC_IF_FAILED(result); return result.GetDescription() != nn::Result::DESCRIPTION_TIMEOUT; } inline void WaitObject::WaitAll(WaitObject* objs[], s32 numObjects) { s32 dummy; NN_UTIL_PANIC_IF_FAILED(WaitMultiple(&dummy, objs, numObjects, true, WAIT_INFINITE)); } inline s32 WaitObject::WaitAny(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout) { s32 ret; nn::Result result = WaitMultiple(&ret, objs, numObjects, false, timeout.GetNanoSeconds()); NN_UTIL_PANIC_IF_FAILED(result); return (result.GetDescription() == nn::Result::DESCRIPTION_TIMEOUT) ? -1 : ret; } inline s32 WaitObject::WaitAny(WaitObject* objs[], s32 numObjects) { s32 ret; NN_UTIL_PANIC_IF_FAILED(WaitMultiple(&ret, objs, numObjects, false, WAIT_INFINITE)); return ret; } }} // namespace nn::os #endif // __cplusplus // 以下、C 用宣言 #include NN_UTIL_DETAIL_CLIBIMPL_DEFINE_ABSTRACT_BUFFER_CLASS(nnosWaitObject) /*! @brief 対応する C++ 関数を参照してください。@ref nn::os::WaitObject::WaitOne */ NN_EXTERN_C bool nnosWaitObjectWaitOne(nnosWaitObject* p, s64 nanoSecondsTimeout); /*! @brief 対応する C++ 関数を参照してください。@ref nn::os::WaitObject::WaitAll */ NN_EXTERN_C bool nnosWaitObjectWaitAll(nnosWaitObject* objs[], s32 numObjects, s64 nanoSecondsTimeout); /*! @brief 対応する C++ 関数を参照してください。@ref nn::os::WaitObject::WaitAny */ NN_EXTERN_C s32 nnosWaitObjectWaitAny(nnosWaitObject* objs[], s32 numObjects, s64 nanoSecondsTimeout); /* NN_OS_SYNCHRONIZATION_H_ */ #endif /* NN_OS_OS_SYNCHRONIZATION_H_ */