1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: os_ContinuationIterator.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: 46347 $ 14 *---------------------------------------------------------------------------*/ 15 16 17 #ifndef NN_OS_OS_CONTINUATIONITERATOR_H_ 18 #define NN_OS_OS_CONTINUATIONITERATOR_H_ 19 20 #ifdef __cplusplus 21 22 #include <nn/Result.h> 23 #include <nn/WithInitialize.h> 24 #include <csetjmp> 25 26 namespace nn { namespace os { 27 28 class Context 29 { 30 private: 31 32 struct Registers 33 { 34 bit32 regs[10]; 35 } m_Registers; 36 37 static void SwitchImpl(bit32 r0, Registers* to); 38 static bit32 SwitchImpl(bit32 r0, Registers* from, Registers* to); 39 static bit32 SwitchImpl(bit32 r0, bit32 r1, Registers* from, Registers* to); 40 static bit32 CallOnOtherStackImpl(bit32 arg0, void* f, Registers* regs, uptr sp); 41 42 public: 43 44 void Initialize(void* pc, uptr sp); 45 void Switch(bit32 r0 = 0) { SwitchImpl(r0, &this->m_Registers); } SwitchFrom(bit32 r0,Context & currentContext)46 bit32 SwitchFrom(bit32 r0, Context& currentContext) { return SwitchImpl(r0, ¤tContext.m_Registers, &this->m_Registers); } SwitchFrom(bit32 r0,bit32 r1,Context & currentContext)47 bit32 SwitchFrom(bit32 r0, bit32 r1, Context& currentContext) { return SwitchImpl(r0, r1, ¤tContext.m_Registers, &this->m_Registers); } 48 CallOnOtherStack(nn::os::Context & context,uptr sp,void * f)49 static bit32 CallOnOtherStack(nn::os::Context& context, uptr sp, void* f) { return CallOnOtherStack(context, sp, f, 0); } CallOnOtherStack(nn::os::Context & context,uptr sp,void * f,bit32 arg0)50 static bit32 CallOnOtherStack(nn::os::Context& context, uptr sp, void* f, bit32 arg0) { return CallOnOtherStackImpl(arg0, f, &context.m_Registers, sp); } CallOnOtherStack(uptr sp,void * f)51 static bit32 CallOnOtherStack(uptr sp, void* f) { return CallOnOtherStack(sp, f, 0); } CallOnOtherStack(uptr sp,void * f,bit32 arg0)52 static bit32 CallOnOtherStack(uptr sp, void* f, bit32 arg0) { Context c; return CallOnOtherStack(c, sp, f, arg0); } 53 54 }; 55 56 class ContinuationIteratorBase 57 { 58 private: 59 60 Context* m_MainContext; 61 Context* m_IteratorContext; 62 Result m_Result; 63 64 static void RunIterator(ContinuationIteratorBase* p); 65 66 protected: 67 68 // With this iterator, override the executing process. 69 virtual Result Run() = 0; 70 ~ContinuationIteratorBase()71 virtual ~ContinuationIteratorBase() {} 72 73 public: 74 75 // Specify stack with stackBottom and initialize 76 void Initialize(void* stackBottom); 77 78 // Return the process to MoveNext. 79 // Can be called only in Run(). 80 // When the return is Failure, cannot call Yield again. 81 Result Yield(); 82 83 // Executes until the next Yield or Run() ends. 84 // When returns with Yield, returns true; when Run() ends, returns false. 85 // When something other than ResultSuccess is specified in result, notification is made of returning forcibly with Run(). 86 // 87 bool MoveNext(Result result = nn::ResultSuccess()); 88 89 // After MoveNext returns false, gets the Run() execution result. 90 // If this value is referenced before MoveNext returns false, operations will be undefined. GetResult()91 Result GetResult() const { return m_Result; } 92 93 }; 94 95 template <class T> 96 class ContinuationIterator : public ContinuationIteratorBase 97 { 98 private: 99 100 T m_Value; 101 102 public: 103 104 // Sets the iterator value. 105 // Can be called only in Run(). SetCurrent(const T & value)106 void SetCurrent(const T& value) { m_Value = value; } 107 108 // Returns the iterator value. 109 // Can be called only in Run(). YieldReturn(const T & value)110 Result YieldReturn(const T& value) { SetCurrent(value); return Yield(); } 111 112 // Gets the iterator value. GetCurrent()113 const T& GetCurrent() const { return m_Value; } 114 115 }; 116 117 }} 118 119 #endif 120 121 #endif 122