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, &currentContext.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, &currentContext.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