1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: os_LightBarrier.h 4 5 Copyright (C)2009-2012 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: 47236 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NN_OS_OS_LIGHTBARRIER_H_ 17 #define NN_OS_OS_LIGHTBARRIER_H_ 18 19 #ifdef __cplusplus 20 21 #include <nn/os/os_WaitableCounter.h> 22 #include <nn/assert.h> 23 #include <nn/WithInitialize.h> 24 #include <nn/util/detail/util_ScopedLockImpl.h> 25 #include <nn/util/util_NonCopyable.h> 26 #include <cstdlib> 27 28 namespace nn { namespace os { 29 30 /* Please see man pages for details 31 32 33 34 35 */ 36 37 /* 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 */ 53 class LightBarrier : private nn::util::NonCopyable<LightBarrier> 54 { 55 private: 56 struct IncrementIfLessThan_1 57 { operatorIncrementIfLessThan_158 bool operator()(s32& x) 59 { 60 if( x < -1 ) 61 { 62 ++x; 63 return true; 64 } 65 else 66 { 67 return false; 68 } 69 } 70 }; 71 72 private: 73 WaitableCounter m_CounterPlus; 74 WaitableCounter m_CounterMinus; 75 s32 m_ReleaseCountAndSign; 76 77 public: 78 //---------------------------------------- 79 // 80 // 81 82 /* 83 84 85 86 87 88 89 90 91 */ LightBarrier()92 LightBarrier() {} 93 94 /* 95 96 97 98 99 100 101 102 103 104 105 */ LightBarrier(s32 numWait)106 explicit LightBarrier(s32 numWait) { Initialize(numWait); } 107 108 /* 109 110 111 112 113 114 115 */ Initialize(s32 numWait)116 void Initialize(s32 numWait) 117 { 118 NN_MIN_TASSERT_( numWait, 1 ); 119 120 *m_CounterPlus = - numWait; 121 *m_CounterMinus = - numWait; 122 m_ReleaseCountAndSign = numWait; 123 } 124 125 /* 126 127 128 129 130 */ Finalize()131 void Finalize() {} 132 133 // 134 135 //---------------------------------------- 136 // 137 // 138 139 /* 140 141 142 143 144 145 146 147 */ GetReleaseCount()148 s32 GetReleaseCount() const { return std::abs(m_ReleaseCountAndSign); } 149 150 /* 151 152 153 154 155 156 157 158 */ GetNumOfWaiting()159 s32 GetNumOfWaiting() const 160 { 161 const s32 relCountAndSign = m_ReleaseCountAndSign; 162 s32 minusRemain; 163 s32 relCount; 164 165 if( relCountAndSign > 0 ) 166 { 167 minusRemain = *m_CounterPlus; 168 relCount = relCountAndSign; 169 } 170 else 171 { 172 minusRemain = *m_CounterMinus; 173 relCount = - relCountAndSign; 174 } 175 176 return (minusRemain == 0) ? 0: relCount + minusRemain; 177 } 178 179 // 180 181 //---------------------------------------- 182 // 183 // 184 185 /* 186 187 188 189 190 191 192 193 */ Await()194 void Await() 195 { 196 const s32 relCountAndSign = m_ReleaseCountAndSign; 197 198 if( relCountAndSign > 0 ) 199 { 200 AwaitImpl(&m_CounterPlus, &m_CounterMinus, relCountAndSign); 201 } 202 else 203 { 204 AwaitImpl(&m_CounterMinus, &m_CounterPlus, - relCountAndSign); 205 } 206 } 207 208 // 209 210 private: AwaitImpl(nn::os::WaitableCounter * pCur,nn::os::WaitableCounter * pNext,s32 relCount)211 void AwaitImpl(nn::os::WaitableCounter* pCur, nn::os::WaitableCounter* pNext, s32 relCount) 212 { 213 IncrementIfLessThan_1 updater; 214 215 if( (*pCur)->AtomicUpdateConditional(updater) ) 216 { 217 pCur->WaitIfLessThan(0); 218 } 219 else 220 { 221 m_ReleaseCountAndSign = - m_ReleaseCountAndSign; 222 **pNext = - relCount; 223 **pCur = 0; 224 pCur->SignalAll(); 225 } 226 } 227 }; 228 229 230 }} // namespace nn::os 231 232 #endif // __cplusplus 233 234 // TODO: Requires an API for C. 235 236 #endif // ifndef NN_OS_OS_LIGHTBARRIER_H_ 237