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