1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_WaitableCounter.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 18508 $
14  *---------------------------------------------------------------------------*/
15 
16 /*
17     @file
18 
19     :include nn/os.h
20 */
21 
22 #ifndef NN_OS_OS_WAITABLETIMER_H_
23 #define NN_OS_OS_WAITABLETIMER_H_
24 
25 #ifdef __cplusplus
26 
27 #include <nn/fnd/fnd_Interlocked.h>
28 #include <nn/util/util_NonCopyable.h>
29 #include <nn/Handle.h>
30 #include <nn/Result.h>
31 #include <nn/svc.h>
32 
33 namespace nn { namespace os {
34 
35 /*
36     @brief     スレッド間でカウンタの数値を管理する同期機構です。
37 
38                内部にカウンタを持ち、このカウンタの数値をスレッド間で安全に操作したり、
39                カウンタの数値に対する条件が成立するまで待ち合わせたりすることができます。
40 */
41 class WaitableCounter
42 {
43 private:
44     static nnHandle s_Handle;
45 
46 private:
47     typedef nn::fnd::InterlockedVariable<s32> ValueType;
48     ValueType   m_Value;        //!< カウンタ
49 
50 public:
51     /*
52         @brief カウンタを初期化します。
53     */
54     static void Initialize();
55 
56     /*
57         @brief カウンタを破棄します。
58     */
59     static void Finalize();
60 
61     ValueType& operator *() { return m_Value; }
62     const ValueType& operator *() const { return m_Value; }
63     ValueType* operator->() { return &m_Value; }
64 
65     /*
66         @brief カウンタの数値が value よりも小さければ、数値をデクリメントして待機します。
67 
68                カウンタの数値が value 以上になるか、シグナルを通知されると待機を解除します。
69 
70         @param[in] value カウンタの数値と比較する値
71 
72         @return 関数の実行結果を返します。
73     */
DecrementAndWaitIfLessThan(s32 value)74     Result DecrementAndWaitIfLessThan(s32 value)
75     {
76         return ArbitrateAddress(nn::os::ARBITRATION_TYPE_DECREMENT_AND_WAIT_IF_LESS_THAN, value);
77     }
78 
79     /*
80         @brief カウンタの数値が value よりも小さければ待機します。
81 
82                カウンタの数値が value 以上になるか、シグナルを通知されると待機を解除します。
83 
84         @param[in] value カウンタと比較する値
85 
86         @return 関数の実行結果を返します。
87     */
WaitIfLessThan(s32 value)88     Result WaitIfLessThan(s32 value)
89     {
90         return ArbitrateAddress(nn::os::ARBITRATION_TYPE_WAIT_IF_LESS_THAN, value);
91     }
92 
93     /*
94         @brief 指定した数の待機しているスレッドに対してシグナルを送ります。
95 
96                オブジェクト数に -1 を指定した場合は全ての待機しているスレッドに対してシグナルを送ります。
97 
98         @param[in] num シグナルを送るスレッド数
99 
100         @return 関数の実行結果を返します。
101     */
Signal(s32 num)102     Result Signal(s32 num)
103     {
104         return ArbitrateAddress(nn::os::ARBITRATION_TYPE_SIGNAL, num);
105     }
106 
107     /*
108         @brief 全ての待機しているスレッドに対してシグナルを送ります。
109 
110         @return 関数の実行結果を返します。
111     */
SignalAll()112     Result SignalAll()
113     {
114         return Signal(-1);
115     }
116 
117 private:
ArbitrateAddress(nn::os::ArbitrationType type,s32 value)118     Result ArbitrateAddress(nn::os::ArbitrationType type, s32 value)
119     {
120         return nn::svc::ArbitrateAddress(s_Handle, reinterpret_cast<uptr>(&m_Value), type, value);
121     }
122 };
123 
124 
125 }} // namespace nn::os
126 
127 #endif // __cplusplus
128 
129 #endif
130