Skip to content

Commit 7987a2a

Browse files
committed
support Thread.Join
1 parent a8c4e6e commit 7987a2a

3 files changed

Lines changed: 196 additions & 165 deletions

File tree

‎CSharp.lua/CoreSystem.Lua/CoreSystem/Threads/Task.lua‎

Lines changed: 131 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
--[[
1+
--[[
22
Copyright 2017 YANG Huan (sy.yanghuan@gmail.com).
33
44
Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,6 +23,7 @@ local addTimer = System.addTimer
2323
local removeTimer = System.removeTimer
2424
local Exception = System.Exception
2525
local NotImplementedException = System.NotImplementedException
26+
local ArgumentNullException = System.ArgumentNullException
2627
local ArgumentOutOfRangeException = System.ArgumentOutOfRangeException
2728

2829
local type = type
@@ -90,27 +91,37 @@ local UnobservedTaskExceptionEventArgs = System.define("System.UnobservedTaskExc
9091
})
9192

9293
local unobservedTaskException
93-
local function addUnobservedTaskException(value)
94-
unobservedTaskException = unobservedTaskException + value
95-
end
96-
97-
local function removeUnobservedTaskException(value)
98-
unobservedTaskException = unobservedTaskException - value
99-
end
100-
10194
local function publishUnobservedTaskException(sender, ueea)
10295
local handler = unobservedTaskException
10396
if handler then
10497
handler(sender, ueea)
10598
end
10699
end
107100

108-
System.define("System.TaskScheduler", {
109-
addUnobservedTaskException = addUnobservedTaskException,
110-
removeUnobservedTaskException = removeUnobservedTaskException
101+
local TaskScheduler = System.define("System.TaskScheduler", {
102+
addUnobservedTaskException = function (value)
103+
unobservedTaskException = unobservedTaskException + value
104+
end,
105+
removeUnobservedTaskException = function (value)
106+
unobservedTaskException = unobservedTaskException - value
107+
end
111108
})
112109

113-
local TaskExceptionHolder = {}
110+
local TaskExceptionHolder = {
111+
__index = false,
112+
__gc = function (this)
113+
if not this.isHandled then
114+
local e = this.exception
115+
if e then
116+
local ueea = UnobservedTaskExceptionEventArgs(e)
117+
publishUnobservedTaskException(this.task, ueea)
118+
if not ueea.observed then
119+
print("Warning: TaskExceptionHolder" , e)
120+
end
121+
end
122+
end
123+
end
124+
}
114125
TaskExceptionHolder.__index = TaskExceptionHolder
115126

116127
local function newTaskExceptionHolder(task, exception)
@@ -124,20 +135,7 @@ local function createExceptionObject(this)
124135
return this.exception
125136
end
126137

127-
function TaskExceptionHolder.__gc(this)
128-
if not this.isHandled then
129-
local e = this.exception
130-
if e then
131-
local ueea = UnobservedTaskExceptionEventArgs(e)
132-
publishUnobservedTaskException(this.task, ueea)
133-
if not ueea.observed then
134-
print("Warning: TaskExceptionHolder" , e)
135-
end
136-
end
137-
end
138-
end
139-
140-
local Task = {}
138+
local Task
141139
local nextTaskId = 1
142140
local currentTask
143141
local completedTask
@@ -157,58 +155,22 @@ local function getId(this)
157155
return id
158156
end
159157

160-
Task.getId = getId
161-
162-
function Task.getCurrentId()
163-
local t = currentTask
164-
if t then
165-
return getId(t)
166-
end
167-
end
168-
169-
function Task.getStatus(this)
170-
return this.status
171-
end
172-
173-
local function getException(this)
174-
if this.status == TaskStatusFaulted then
175-
return createExceptionObject(this.data)
176-
end
177-
return nil
178-
end
179-
180-
Task.getException = getException
181-
182158
local function isCompleted(this)
183159
local status = this.status
184160
return status == TaskStatusRanToCompletion or status == TaskStatusFaulted or status == TaskStatusCanceled
185161
end
186162

187-
Task.getIsCompleted = isCompleted
188-
189-
function Task.getIsCanceled(this)
190-
return this.status == TaskStatusCanceled
191-
end
192-
193-
function Task.getIsFaulted(this)
194-
return this.status == TaskStatusFaulted
195-
end
196-
197163
local function fromResult(result)
198164
return setmetatable({ status = TaskStatusRanToCompletion, data = result }, Task)
199165
end
200166

201-
Task.FromResult = fromResult
202-
203167
local function fromCanceled(cancellationToken)
204168
if cancellationToken and cancellationToken:getIsCancellationRequested() then
205169
throw(ArgumentOutOfRangeException("cancellationToken"))
206170
end
207171
return setmetatable({ status = TaskStatusCanceled, data = cancellationToken }, Task)
208172
end
209173

210-
Task.FromCanceled = fromCanceled
211-
212174
local function getCompletedTask()
213175
local t = completedTask
214176
if t == nil then
@@ -218,8 +180,6 @@ local function getCompletedTask()
218180
return t
219181
end
220182

221-
Task.getCompletedTask = getCompletedTask
222-
223183
local function trySetComplete(this, status, data)
224184
if isCompleted(this) then
225185
return false
@@ -257,46 +217,6 @@ local function newWaitingTask(isVoid)
257217
return setmetatable({ status = TaskStatusWaitingForActivation, isVoid = isVoid }, Task)
258218
end
259219

260-
function Task.Delay(delay, cancellationToken)
261-
if type(delay) == "table" then
262-
delay = trunc(delay:getTotalMilliseconds())
263-
if delay < -1 or delay > 2147483647 then
264-
throw(ArgumentOutOfRangeException("delay"))
265-
end
266-
elseif delay < -1 then
267-
throw(ArgumentOutOfRangeException("millisecondsDelay"))
268-
end
269-
270-
if cancellationToken and cancellationToken:getIsCancellationRequested() then
271-
return fromCanceled(cancellationToken)
272-
elseif delay == 0 then
273-
return getCompletedTask()
274-
end
275-
276-
local t = newWaitingTask()
277-
local timerId, registration
278-
279-
if cancellationToken and cancellationToken:getCanBeCanceled() then
280-
registration = cancellationToken.source:register(function ()
281-
local success = trySetCanceled(t, cancellationToken)
282-
if success and timerId then
283-
removeTimer(timerId)
284-
end
285-
end)
286-
end
287-
288-
if delay ~= -1 then
289-
timerId = addTimer(function ()
290-
local success = trySetResult(t)
291-
if success and registration then
292-
registration:Dispose()
293-
end
294-
end, delay)
295-
end
296-
297-
return t
298-
end
299-
300220
local function getContinueActions(task)
301221
local continueActions = task.continueActions
302222
if continueActions == nil then
@@ -306,24 +226,6 @@ local function getContinueActions(task)
306226
return continueActions
307227
end
308228

309-
function Task.ContinueWith(this, continuationAction)
310-
local t = newWaitingTask()
311-
local function f()
312-
try(function ()
313-
assert(trySetResult(t, continuationAction()))
314-
end, function (e)
315-
assert(trySetException(t, e))
316-
end)
317-
end
318-
if isCompleted(this) then
319-
post(f)
320-
else
321-
local continueActions = getContinueActions(task)
322-
tinsert(continueActions, f)
323-
end
324-
return t
325-
end
326-
327229
local function await(t, task)
328230
assert(t.co)
329231
local continueActions = getContinueActions(task)
@@ -352,22 +254,112 @@ local function await(t, task)
352254
end
353255
end
354256

355-
function Task.await(this, task)
356-
local status = task.status
357-
if status == TaskStatusWaitingForActivation then
358-
return await(this, task)
359-
elseif status == TaskStatusRanToCompletion then
360-
return task.data
361-
elseif status == TaskStatusFaulted then
362-
throw(createExceptionObject(task.data))
363-
elseif status == TaskStatusCanceled then
364-
throw(TaskCanceledException(task))
365-
else
366-
return await(this, task)
367-
end
368-
end
257+
Task = System.define("System.Task", {
258+
__ctor__ = function (this, action, state)
259+
if action == nil then throw(ArgumentNullException("action")) end
260+
this.status = TaskStatusCreated
261+
this.data = function ()
262+
action(state)
263+
end
264+
end,
265+
getId = getId,
266+
getCurrentId = function ()
267+
local t = currentTask
268+
if t then
269+
return getId(t)
270+
end
271+
end,
272+
getStatus = function (this)
273+
return this.status
274+
end,
275+
getException = function (this)
276+
if this.status == TaskStatusFaulted then
277+
return createExceptionObject(this.data)
278+
end
279+
return nil
280+
end,
281+
getIsCompleted = isCompleted,
282+
getIsCanceled = function (this)
283+
return this.status == TaskStatusCanceled
284+
end,
285+
getIsFaulted = function (this)
286+
return this.status == TaskStatusFaulted
287+
end,
288+
FromResult = fromResult,
289+
FromCanceled = fromCanceled,
290+
getCompletedTask = getCompletedTask,
291+
Delay = function (delay, cancellationToken)
292+
if type(delay) == "table" then
293+
delay = trunc(delay:getTotalMilliseconds())
294+
if delay < -1 or delay > 2147483647 then
295+
throw(ArgumentOutOfRangeException("delay"))
296+
end
297+
elseif delay < -1 then
298+
throw(ArgumentOutOfRangeException("millisecondsDelay"))
299+
end
300+
301+
if cancellationToken and cancellationToken:getIsCancellationRequested() then
302+
return fromCanceled(cancellationToken)
303+
elseif delay == 0 then
304+
return getCompletedTask()
305+
end
306+
307+
local t = newWaitingTask()
308+
local timerId, registration
369309

370-
System.define("System.Task", Task)
310+
if cancellationToken and cancellationToken:getCanBeCanceled() then
311+
registration = cancellationToken.source:register(function ()
312+
local success = trySetCanceled(t, cancellationToken)
313+
if success and timerId then
314+
removeTimer(timerId)
315+
end
316+
end)
317+
end
318+
319+
if delay ~= -1 then
320+
timerId = addTimer(function ()
321+
local success = trySetResult(t)
322+
if success and registration then
323+
registration:Dispose()
324+
end
325+
end, delay)
326+
end
327+
328+
return t
329+
end,
330+
ContinueWith = function (this, continuationAction)
331+
if continuationAction == nil then throw(ArgumentNullException("continuationAction")) end
332+
local t = newWaitingTask()
333+
local function f()
334+
try(function ()
335+
assert(trySetResult(t, continuationAction()))
336+
end, function (e)
337+
assert(trySetException(t, e))
338+
end)
339+
end
340+
if isCompleted(this) then
341+
post(f)
342+
else
343+
local continueActions = getContinueActions(task)
344+
tinsert(continueActions, f)
345+
end
346+
return t
347+
end,
348+
await = function (this, task)
349+
local status = task.status
350+
if status == TaskStatusWaitingForActivation then
351+
return await(this, task)
352+
elseif status == TaskStatusRanToCompletion then
353+
return task.data
354+
elseif status == TaskStatusFaulted then
355+
throw(createExceptionObject(task.data))
356+
elseif status == TaskStatusCanceled then
357+
throw(TaskCanceledException(task))
358+
else
359+
return await(this, task)
360+
end
361+
end
362+
})
371363

372364
local taskCoroutinePool = {}
373365
local function taskCoroutineCreate(t, f)
@@ -409,4 +401,4 @@ end
409401

410402
function System.async(f, ...)
411403
return async(f, nil, ...)
412-
end
404+
end

0 commit comments

Comments
 (0)