博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
A Threads class with coroutine
阅读量:6582 次
发布时间:2019-06-24

本文共 5313 字,大约阅读时间需要 17 分钟。

hot3.png

A Threads class with coroutine

Introduction

Problem description

When I tried to run some functions like terrain generating. Because it need a long time to finish, so I have to face a black screen without any information appear. This is because of the mechanism of Codea:

when setup() is running, the draw() won't run, when setup() is finished, it will run the draw(). But these functions must run once, so they need to be put into setup().

When I use these functions in setup() and I want to see some information drawing on the screen, how can I do?

I found coroutine can deal with this problem, then I began to learn it.

Solution

I am learning and writing a Threads class. Using it we can solve the problem.

Threads class

Class code

The class code

--# ThreadsThreads = class()function Threads:init()    self.threads = {}        self.taskList = {}    self.time = os.clock()       self.timeTick = 0.01    self.taskID = 1    self.taskStatus = {}    self.taskVT = {}    self.img = image(100,100)end-- Add task function into the task listfunction Threads:addTaskToList(task)    local t = function() task() end    table.insert(self.taskList, t)end-- Create coroutine for all task, run oncefunction Threads:job()        local n = #self.taskList    for id = 1, n do        -- local f = function () self.taskList[id]() end        local f = function () self:taskUnit(id) end        local co = coroutine.create(f)        table.insert(self.threads, co)           -- Record all tasks' status,  now should be suspended        self.taskStatus[id] = coroutine.status(co)    endend-- Task unitfunction Threads:taskUnit(id)    self.taskID = id    self.taskList[id]()    -- self:switchPoint(id)          -- self.taskStatus[id] = "Finished" end-- Switch point, put this function into the task functionfunction Threads:switchPoint(id)    -- Switch task,when its timetick is used and task have not finished    if (os.clock() - self.time) >= self.timeTick then           -- Debug info, do not put the print into the task function        print("hello: No."..id.." is "..self.taskStatus[id])          -- self:visual(id)        -- reset task time        self.time = os.clock()          -- Pause the task         coroutine.yield()        endend-- Put this function into draw()function Threads:dispatch()    local n = #self.threads    if n == 0 then return end       for i = 1, n do		-- Record the current task		self.taskID = i    		local status = coroutine.resume(self.threads[i])		-- Record all the tasks' status		self.taskStatus[i] = coroutine.status(self.threads[i])		-- If task finished, then remove it from self.threads, and return		if not status then            self.taskStatus[i] = "Finished"             table.remove(self.threads, i)            -- table.remove(self.taskList,i)            return        end    endend --[[function Threads:visual(id)    local n = #self.taskList    local vt = {}    background(18, 16, 16, 255)    setContext(self.img)    pushStyle()    strokeWidth(1)    fill(255, 211, 0, 255)    -- if self.taskID == 1 then fill(241, 7, 7, 255) else fill(255, 211, 0, 255) end    local w,h = self.img.width/n, self.img.height/n    local x,y = 0,0    for i = 1, n do        vt[i] = function () rect(100+x+(i-1)*w,100+y+(i-1)*h,w,h) end    end        popStyle()    setContext()    -- sprite(self.img,300,300)    -- vt[self.taskID]()    print("id: "..id)    vt[id]()end--]]```	The test code:

--# Main function setup() print("Thread testing ...")

myT = Threads()myT.timeTick = 1/60myT:addTaskToList(tt)myT:addTaskToList(oo)myT:addTaskToList(mf)myT:addTaskToList(pk)--[[ myT.taskList[2]()--]]myT:job()print(unpack(myT.taskList))

end

function draw() background(0)

myT:dispatch()fill(244, 27, 27, 255)print("2: "..myT.taskStatus[1])print("length: "..#myT.taskList)sysInfo()

end

-- The task functions

function tt () while true do -- print("tt: "..os.clock()) myT:switchPoint(myT.taskID) end end

function oo () while true do -- print("oo: "..os.clock()) myT:switchPoint(myT.taskID) end end

function mf () local k = 0 for i=1,10000000 do k = k + i -- print("mf: "..k) -- If the time >= timeTick then pause myT:switchPoint(myT.taskID) end end

function pk () local k = 0 for i=1,10000000 do k = k + i -- print("pk: "..k) -- If the time >= timeTick then pause myT:switchPoint(myT.taskID) end end

###	UsageAssume we have a function `createTerrain()` to generate the terrain in `setup()`, and it will take a long time, we can do like below:

function setup()

myT = Threads()myT.timeTick = 1/60myT:addTaskToList(createTerrain)myT:job()

end

function draw() background(0)

myT:dispatch()drawLoadingScreen()

end

-- This is the loading screen function drawLoadingScreen() ... -- Show some information text("Creating the terrain, please wait...") ... end

-- The function will run for a long time function createTerrain() ... for i=1,10000 do for j= 1, 100000 do ... -- Put the switchPoint() here myT:switchPoint(myT.taskID) end end ...

for i=1,200000 do	for j= 1, 300000 do		...		-- Put the switchPoint() here		myT:switchPoint(myT.taskID)	endend...

end

If the function is a method of a class, like `Map:createTerrain()`, we can load it like below:

myT:addTaskToList(function () Map:createTerrain() end)

OK, it is all.BTW. This is for the newbie, if you are experienced, please ignore it. :)

转载于:https://my.oschina.net/freeblues/blog/692642

你可能感兴趣的文章
pl/sql development 查询的数据复制到excel
查看>>
自定义指令的参数
查看>>
python实现进度条
查看>>
MySQL之事件学习整理
查看>>
Android 一个应用启动另一个应用的说明
查看>>
阿里云CentOS7服务器利用LVM分区挂载磁盘全记录
查看>>
asterisk的安装方法
查看>>
Setting up the Web Admin Tool in LDAP 6.x to communicate via SSL
查看>>
IOS开发一些常用功能
查看>>
SQL好习惯:编写支持可搜索的SQL
查看>>
Shadowbox
查看>>
【 程 序 员 】:伤不起的三十岁,你还有多远 ?
查看>>
Skype 4.1 Linux 发布,支持微软帐号登录
查看>>
hexdump 1.8 发布,十六进制数据查看工具
查看>>
openldap安装
查看>>
C++ istream::peek()
查看>>
[leetcode]count and say
查看>>
flex java socket通信
查看>>
比VC的TRACE还要好的调试命令
查看>>
润乾报表 - 缓存问题
查看>>