zoukankan      html  css  js  c++  java
  • lua:写了个基于协程的task调度库

    写了一个(不完整的)基于协程的task调度库

    sample code如下

    my_spawn(
      function ()
        print('f: 1')
        
        local t1 = my_spawn(
          function ()
            print('f: 3')
            task_yield_to_be_schedule()
            print('f: 4')
          end
        )
        
        --task_yield_to_be_schedule()
        my_wait_task(t1)
        print('f: 2')
      end
    )
    
    local num_run = 0
    while my_run_once() do
      dbgprint('>>exec ', num_run)
      num_run = num_run + 1
    end

    features

    • 支持spwan
    • 支持在task里面spawn
    • 支持task里面yield
    • 支持task里面等待其他task

    todo

    • 支持在task里面sleep
    • 支持在task里面设置和等待event

    完整源代码如下

    require('mobdebug').coro() 
    local inspect = require('inspect')
    
    local debug_on = true
    
    local function dbgprint(...)
      if debug_on then
        print(...)
      end
    end
    
    if false then
      function f()
        print('in f')
        coroutine.yield(100)
        print('in f2')
        
      end
    
      local task1 = coroutine.create(f)
      print(coroutine.status(task1))
      local ret, r2, r3 = coroutine.resume(task1)
      print(ret)
      print(coroutine.status(task1))
      print(coroutine.resume(task1))
      print(coroutine.resume(task1))
      print(coroutine.status(task1))
      
      return
    end
    
    
    
    -- scheduler
    -- lowlevel support: spawn, wait, events and timeout
    
    -- to be run tasks
    local tasks_to_be_scheduled = {}
    
    -- to be timeout tasks
    local tasks_to_be_timeout = {}
    
    -- to be set event tasks
    local tasks_to_be_event = {}
    
    -- to be waited tasks, this is a map where key is task handle, value is the tasks waiting this task
    local tasks_to_be_wait = {}
    
    -- task yield flags
    local yield_flag_to_be_schedule = 1
    local yield_flag_timeout = 2
    local yield_flag_event = 3
    local yield_flag_wait_task = 3
    
    function my_spawn(f)
      local t = coroutine.create(f)
      table.insert(tasks_to_be_scheduled, t)
      return t
    end
    
    function my_run_once()
      
      -- loop to be scueduled tasks
      if #tasks_to_be_scheduled > 0 then
        
        -- fetch a task
        local t = table.remove(tasks_to_be_scheduled, 1)
        assert(coroutine.status(t)=="suspended")
        
        -- exec
        local ret, data1, data2 = coroutine.resume(t)
        dbgprint ('>>resume coroutine returns ', ret, inspect(data1), data2)
        assert(ret)
        
        -- handle following
        if coroutine.status(t) ~= 'dead' then
          assert(data1 and data1.yield_flag)
          local dispatch={}
          dispatch[yield_flag_to_be_schedule] = function ()
            table.insert(tasks_to_be_scheduled, t)
          end
          
          dispatch[yield_flag_wait_task] = function ()
          end
          
          local disp = dispatch[data1.yield_flag]
          if disp then
            disp()
          else
            assert(0)
          end
        else
          -- loop to see who are waiting this task?
          local tasks_to_be_schedule = tasks_to_be_wait[t]
          if tasks_to_be_schedule then
            dbgprint ('>>trigger depent tasks ', inspect(tasks_to_be_schedule))
            for i, task_to_be_schedule in ipairs(tasks_to_be_schedule) do
              table.insert(tasks_to_be_scheduled, task_to_be_schedule)
            end
            tasks_to_be_wait[t] = nil
          end
          
        end
        
        return true
      end
      
      return false
    end
    
    function task_yield_to_be_schedule()
      coroutine.yield ({yield_flag=yield_flag_to_be_schedule})
    end
    
    function my_wait_task(t)
      -- when t done, need notify this_task
      local this_task = coroutine.running()
      if not tasks_to_be_wait[this_task] then
        tasks_to_be_wait[t] = {this_task}
      else
        table.insert(tasks_to_be_wait[t], this_task)
      end
      
      -- yield from current task
      coroutine.yield ({yield_flag=yield_flag_wait_task, handle=t})
    end
    
    my_spawn(
      function ()
        print('f: 1')
        
        local t1 = my_spawn(
          function ()
            print('f: 3')
            task_yield_to_be_schedule()
            print('f: 4')
          end
        )
        
        --task_yield_to_be_schedule()
        my_wait_task(t1)
        print('f: 2')
      end
    )
    
    local num_run = 0
    while my_run_once() do
      dbgprint('>>exec ', num_run)
      num_run = num_run + 1
    end
  • 相关阅读:
    PAT (Advanced Level) Practise:1008. Elevator
    练习题-二维数组中的查找
    PAT (Basic Level) Practise:1028. 人口普查
    PAT (Basic Level) Practise:1014. 福尔摩斯的约会
    PAT (Basic Level) Practise:1019. 数字黑洞
    c++ 二进制文件读写
    c/c++ linux/windows 读取目录下的所有文件名
    C 语言实现 Linux touch 命令
    c++读写csv
    linux nohup【转】
  • 原文地址:https://www.cnblogs.com/cutepig/p/11055612.html
Copyright © 2011-2022 走看看