zoukankan      html  css  js  c++  java
  • 跨平台c++ Coroutine,仿unity3d实现

    不多说,贴代码:

      4 #include "stdafx.h"
      5 #include <list>
      6 #include <thread>  
      7 #include <chrono>
      8 
      9 struct ICoroutine
     10 {
     11     virtual void reset(){}
     12     virtual bool move_next(int & r, float & fv) { return false; }
     13     virtual ~ICoroutine() {}
     14 public:
     15     float mWaitSeconds;
     16 };
     17 
     18 template<typename T>
     19 struct _IGenerator : public ICoroutine
     20 {
     21     T* _stack;
     22     int _line;
     23     _IGenerator() :_stack(0), _line(-1) {}
     24     virtual void reset()
     25     {
     26         _line = -1;
     27     }
     28     void _push() { T* n = new T; *n = *static_cast<T*>(this); _stack = n; }
     29     bool _pop() { if (!_stack) return false; T* t = _stack; *static_cast<T*>(this) = *_stack; t->_stack = 0; delete t; return true; }
     30     ~_IGenerator() { while (_pop()); }
     31 };
     32 
     33 #define $coroutine(NAME) struct NAME : public _IGenerator<NAME>
     34 
     35 
     36 #define $begin virtual bool move_next(int& _rv, float& _rv2) { 
     37                       if(_line < 0) _line=0; 
     38                                               $START: switch(_line) { case 0:;
     39 
     40 #define $stop  } _line = 0; if(_pop()) goto $START; return false; }
     41 
     42 #define $restart(WITH) { _push(); _stack->_line = __LINE__; _line=0; WITH; goto $START; case __LINE__:; }
     43 
     44 #define $yield(V)     
     45           do {
     46               _line=__LINE__;
     47               _rv = (V); return true; case __LINE__:;
     48                     } while (0)
     49 
     50 #define $yield_f(V, V2)     
     51           do {
     52               _line=__LINE__;
     53               _rv = (V); _rv2 = V2; return true; case __LINE__:;
     54                               } while (0)
     55 
     56 
     57 enum CoroutineState
     58 { 
     59     CO_None, 
     60     CO_WaitForNextUpdate, 
     61     CO_WaitForSeconds,
     62     CO_Exit
     63 };
     64 
     65 class GScheduler
     66 {
     67 protected:
     68     std::list<ICoroutine *> mActivityGList;
     69     std::list<ICoroutine *> mWaitingGList;
     70     std::list<ICoroutine *> mDeadingGList;
     71 
     72     std::list<ICoroutine *> mGList;
     73 
     74     void DestroyAllCoroutine()
     75     {
     76         std::list<ICoroutine *>::iterator iter;
     77         for (iter = mGList.begin(); iter != mGList.end(); iter++)
     78         {
     79             ICoroutine * co = *iter;
     80             delete co;
     81         }
     82         mGList.clear();
     83         mDeadingGList.clear();
     84         mWaitingGList.clear();
     85         mActivityGList.clear();
     86     }
     87 public:
     88     ~GScheduler()
     89     {
     90         DestroyAllCoroutine();
     91     }
     92 
     93 
     94     template<typename T, typename T2>
     95     ICoroutine* StartCoroutine(T2 * tObj)
     96     {
     97         ICoroutine * gen = new T(tObj);
     98         mGList.push_back(gen);
     99         mActivityGList.push_back(gen);
    100         return gen;
    101     }
    102     
    103     void StopCoroutine(ICoroutine *)
    104     {        
    105     }
    106 
    107     void RestartAllCoroutine()
    108     {
    109         std::list<ICoroutine *>::iterator iter;
    110         for (iter = mGList.begin(); iter != mGList.end(); iter++)
    111         {
    112             ICoroutine * co = *iter;
    113             co->reset();
    114             mActivityGList.push_back(co);
    115         }
    116     }
    117 
    118     void StopAllCoroutine()
    119     {
    120         mDeadingGList.clear();
    121         mWaitingGList.clear();
    122         mActivityGList.clear();
    123     }
    124     void UpdateAllCoroutine(float dt)
    125     {
    126         std::list<ICoroutine *>::iterator iter, next;
    127         for (iter = mWaitingGList.begin(); iter != mWaitingGList.end();iter = next)
    128         {
    129             next = iter; next++;
    130 
    131             ICoroutine * co = *iter;
    132             co->mWaitSeconds -= dt;
    133             if (co->mWaitSeconds <= 0)
    134             {
    135                 next = mWaitingGList.erase(iter);
    136                 mActivityGList.push_back(co);
    137             }
    138         }
    139 
    140         for (iter = mActivityGList.begin(); iter != mActivityGList.end(); iter = next)
    141         {
    142             next = iter; next++;
    143 
    144             ICoroutine * co = *iter;
    145             
    146             bool isDeading = false;
    147 
    148             int  retValue = 0;
    149             float retFValue = 0;
    150             if (!co->move_next(retValue, retFValue))
    151             {
    152                 isDeading = true;
    153             }
    154             CoroutineState state = (CoroutineState)retValue;
    155             if (state == CO_Exit)
    156             {
    157                 isDeading = true;
    158             }
    159             else if (state == CO_WaitForNextUpdate)
    160             {
    161                 
    162             }
    163             else if (state == CO_WaitForSeconds)
    164             {
    165                 float seconds = retFValue;
    166                 co->mWaitSeconds = seconds;
    167                 next = mActivityGList.erase(iter);
    168                 mWaitingGList.push_back(co);
    169             }
    170 
    171             if (isDeading)
    172             {
    173                 next = mActivityGList.erase(iter);
    174                 mDeadingGList.push_back(co);
    175             }
    176         }
    177     }
    178 };
    179 //**********************************************************************************************************
    //以下是测试程序: 180 class TestCoroutine1; 181 class TestCoroutine2; 182 class UIMain : public GScheduler 183 { 184 public: 185 UIMain() 186 { 187 } 188 void Enable() 189 { 190 RestartAllCoroutine(); 191 } 192 void Disable() 193 { 194 StopAllCoroutine(); 195 } 196 197 void Start() 198 { 199 ICoroutine *testCo = StartCoroutine<TestCoroutine1, UIMain>(this); 200 StartCoroutine<TestCoroutine2, UIMain>(this); 201 } 202 203 void Update(float dt) 204 { 205 UpdateAllCoroutine(dt); 206 } 207 208 void Test1(int v) 209 { 210 printf("Test1, v = %d ", v); 211 } 212 void Test2(int v) 213 { 214 printf("Test2, v = %d ", v); 215 } 216 }; 217 218 219 $coroutine(TestCoroutine1) 220 { 221 UIMain* n; 222 TestCoroutine1(UIMain* root = 0) : n(root) {} 223 int i = 0; 224 $begin 225 for (i = 0; i < 3; i++) 226 { 227 n->Test1(i); 228 $yield(CO_WaitForNextUpdate); 229 } 230 $yield(CO_Exit); 231 n->Test1(10); 232 $stop 233 }; 234 235 $coroutine(TestCoroutine2) 236 { 237 UIMain* n; 238 TestCoroutine2(UIMain* root = 0) : n(root) {} 239 int i = 0; 240 $begin 241 for (i = 3; i < 6; i++) 242 { 243 n->Test2(i); 244 $yield_f(CO_WaitForSeconds, 0.5f); 245 } 246 $yield(CO_Exit); 247 n->Test1(99); 248 $stop 249 }; 250 251 252 253 int _tmain(int argc, _TCHAR* argv[]) 254 { 255 UIMain uiMain; 256 257 uiMain.Enable(); 258 uiMain.Start(); 259 260 float dt = 0.05f; 261 float time = 0; 262 while (true) 263 { 264 uiMain.Update(dt); 265 std::this_thread::sleep_for(std::chrono::milliseconds((int)(dt*1000))); 266 time += dt; 267 if (time > 10) //10秒后重开协程 268 { 269 uiMain.Disable(); 270 uiMain.Enable(); //重新开始协程 271 time = 0; 272 } 273 } 274 return 0; 275 }
  • 相关阅读:
    VS2005编译mysql5.1.68
    用boost库实现traceroute小工具
    linux内核选项部分翻译
    linux 内核中的锁机制RCU
    先装windows 还是linux ?
    U盘装ubuntu
    编译linux内核3.0
    root密码丢失了怎么办?
    linux配置文件
    新一代linux文件系统btrfs
  • 原文地址:https://www.cnblogs.com/corefans/p/4763723.html
Copyright © 2011-2022 走看看