@@ -4,6 +4,13 @@ local getmetatable = getmetatable
44local xpcall = xpcall
55local math_floor = math.floor
66local math_ceil = math.ceil
7+ local coroutine_resume = coroutine.resume
8+ local coroutine_status = coroutine.status
9+ local coroutine_running = coroutine.running
10+ local coroutine_create = coroutine.create
11+ local yield = coroutine.yield
12+ local pcall = pcall
13+ local unpack = unpack
714
815table .unpack = unpack
916
@@ -36,45 +43,50 @@ function math.type(x)
3643 end
3744end
3845
39- local coroutine_resume = coroutine.resume
40- local coroutine_status = coroutine.status
41- local coroutine_running = coroutine.running
46+
4247
4348local cancel_table = setmetatable ({}, { __mode = ' kv' })
4449
4550function coroutine .resume (co , ...)
46- if cancel_table [co ] then
47- return false , ' cannot resume dead coroutine'
51+ local results = { pcall (coroutine_resume , co , ... ) }
52+ local ok = results [1 ]
53+ if not ok then
54+ local reason = results [2 ]
55+ if reason == " cancel" then
56+ return false , ' cannot resume dead coroutine'
57+ end
4858 end
4959
50- return coroutine_resume ( co , ... )
60+ return ok , unpack ( results , 2 )
5161end
5262
53- function coroutine . status ( co )
54- if cancel_table [ co ] then
55- return ' dead '
56- end
63+ -- donot return 'dead' status
64+ -- function coroutine.status(co)
65+ -- return coroutine_status(co)
66+ -- end
5767
58- return coroutine_status (co )
68+ -- 要实现取消, 只能在协程内的调用通过错误让协程消亡
69+ function coroutine .yield (...)
70+ if cancel_table [coroutine_running ()] then
71+ error (" cancel" )
72+ end
73+ return yield (... )
5974end
6075
6176function coroutine .close (co )
6277 if coroutine_status (co ) == ' suspended' then
6378 cancel_table [co ] = true
79+ return true
6480 end
81+ return false
6582end
6683
6784function defer (toBeClosed , callback )
6885 local ctype = type (toBeClosed )
6986 local meta = getmetatable (toBeClosed )
70- local closeCallback = nil
7187 local ok , result
7288
73- local co = coroutine_running ()
74- if coroutine.status (co ) ~= ' dead' then
75- ok , result = xpcall (callback , log .error )
76- end
77-
89+ ok , result = xpcall (callback , log .error )
7890 if meta and meta .__close then
7991 meta .__close (toBeClosed )
8092 elseif ctype == ' function' then
0 commit comments