1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_LightEvent.cpp
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: 16480 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/os/os_LightEvent.h>
17
18 //---------------------------------------------------------------------------
19
20
21 namespace nn {
22 namespace os {
23
24 // フラグがセットされているかどうかを取得します。
TryWait()25 bool LightEvent::TryWait()
26 {
27 if( *m_Counter == SIGNALED_MANUAL )
28 {
29 // 手動リセットなのでフラグのリセットは行いません。
30 return true;
31 }
32 else
33 {
34 // フラグが設定されていれば、フラグをリセットして true を返します。
35 return m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO;
36 }
37 }
38
39 // フラグがセットされるまで待機します。
Wait()40 void LightEvent::Wait()
41 {
42 for(;;)
43 {
44 switch( *m_Counter )
45 {
46 // フラグがセットされるまで待機、フラグはクリアしません。
47 case NOT_SIGNALED_MANUAL: m_Counter.WaitIfLessThan(0); return;
48
49 // フラグはセットされているので待機しません。
50 case SIGNALED_MANUAL: return;
51
52 // フラグはセットされていないので待機します。
53 case NOT_SIGNALED_AUTO: break;
54
55 // フラグはセットされているので待機しません。フラグはリセットします。
56 case SIGNALED_AUTO:
57 {
58 if( m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO )
59 {
60 return;
61 }
62 }
63 break;
64 }
65
66 // フラグがセットされるまで待機します
67 // フラグがセットされれば m_Counter が NOT_SIGNALED_AUTO から SIGNALED_AUTO に変わります。
68 m_Counter.WaitIfLessThan(0);
69 }
70 }
71
72 // フラグをセットします。
Signal()73 void LightEvent::Signal()
74 {
75 if( *m_Counter == NOT_SIGNALED_AUTO )
76 {
77 *m_Counter = SIGNALED_AUTO;
78 // 自動リセットの場合は、優先度の高いスレッドを起床します。
79 // スレッド起床と同時にフラグはリセットされます。
80 m_Counter.Signal(1);
81 }
82 else if( *m_Counter == NOT_SIGNALED_MANUAL )
83 {
84 *m_Counter = SIGNALED_MANUAL;
85 // 手動リセットの場合は、待機しているすべてのスレッドを起床します。
86 // スレッドが起床してもフラグはリセットされません。
87 m_Counter.SignalAll();
88 }
89 // 待機しているスレッドが存在しなければフラグはそのままです。
90 }
91
92 // フラグがセットされるのを待機しているスレッドを解放します。
Pulse()93 void LightEvent::Pulse()
94 {
95 switch( *m_Counter )
96 {
97 case SIGNALED_MANUAL:
98 *m_Counter = NOT_SIGNALED_MANUAL;
99 // not break
100 case NOT_SIGNALED_MANUAL:
101 // フラグのセットを待機しているすべてのスレッドを起床します。
102 // スレッド起床と同時にフラグはリセットされます。
103 m_Counter.SignalAll();
104 break;
105
106 case NOT_SIGNALED_AUTO:
107 // フラグのセットを待機しているスレッドのうち、
108 // 最も優先度の高いスレッドを起床します。
109 // スレッド起床と同時にフラグはリセットされます。
110 m_Counter.Signal(1);
111 break;
112
113 case SIGNALED_AUTO:
114 // フラグをリセットします。
115 *m_Counter = NOT_SIGNALED_AUTO;
116 break;
117 }
118 }
119
120 // フラグをクリアします。
ClearSignal()121 void LightEvent::ClearSignal()
122 {
123 if( *m_Counter == SIGNALED_MANUAL )
124 {
125 *m_Counter = NOT_SIGNALED_MANUAL;
126 }
127 else if( *m_Counter == SIGNALED_AUTO )
128 {
129 *m_Counter = NOT_SIGNALED_AUTO;
130 }
131 }
132
133 }
134 }
135
136
137
138 using namespace nn;
139
140
141 // C 関数の定義
142
143 #include <new>
144
145 using namespace nn::os;
146
147 extern "C" {
148
nnosLightEventInitialize(nnosLightEvent * p,bool isManualReset)149 void nnosLightEventInitialize(nnosLightEvent* p, bool isManualReset)
150 {
151 new (p) LightEvent(isManualReset);
152 }
153
nnosLightEventIsSignaled(nnosLightEvent * p)154 bool nnosLightEventIsSignaled(nnosLightEvent* p)
155 {
156 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
157 return pLightEvent->IsSignaled();
158 }
159
nnosLightEventIsManualReset(nnosLightEvent * p)160 bool nnosLightEventIsManualReset(nnosLightEvent* p)
161 {
162 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
163 return pLightEvent->IsManualReset();
164 }
165
nnosLightEventTryWait(nnosLightEvent * p)166 bool nnosLightEventTryWait(nnosLightEvent* p)
167 {
168 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
169 return pLightEvent->TryWait();
170 }
171
nnosLightEventWait(nnosLightEvent * p)172 void nnosLightEventWait(nnosLightEvent* p)
173 {
174 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
175 pLightEvent->Wait();
176 }
177
nnosLightEventSignal(nnosLightEvent * p)178 void nnosLightEventSignal(nnosLightEvent* p)
179 {
180 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
181 pLightEvent->Signal();
182 }
183
nnosLightEventPulse(nnosLightEvent * p)184 void nnosLightEventPulse(nnosLightEvent* p)
185 {
186 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
187 pLightEvent->Pulse();
188 }
189
nnosLightEventClearSignal(nnosLightEvent * p)190 void nnosLightEventClearSignal(nnosLightEvent* p)
191 {
192 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
193 pLightEvent->ClearSignal();
194 }
195
nnosLightEventFinalize(nnosLightEvent * p)196 void nnosLightEventFinalize(nnosLightEvent* p)
197 {
198 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
199 pLightEvent->Finalize();
200 pLightEvent->~LightEvent();
201 }
202
203 } // extern "C"
204