1- --[[
1+ --[[
22Copyright 2017 YANG Huan (sy.yanghuan@gmail.com).
33
44Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,6 +23,7 @@ local addTimer = System.addTimer
2323local removeTimer = System .removeTimer
2424local Exception = System .Exception
2525local NotImplementedException = System .NotImplementedException
26+ local ArgumentNullException = System .ArgumentNullException
2627local ArgumentOutOfRangeException = System .ArgumentOutOfRangeException
2728
2829local type = type
@@ -90,27 +91,37 @@ local UnobservedTaskExceptionEventArgs = System.define("System.UnobservedTaskExc
9091})
9192
9293local 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-
10194local function publishUnobservedTaskException (sender , ueea )
10295 local handler = unobservedTaskException
10396 if handler then
10497 handler (sender , ueea )
10598 end
10699end
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+ }
114125TaskExceptionHolder .__index = TaskExceptionHolder
115126
116127local function newTaskExceptionHolder (task , exception )
@@ -124,20 +135,7 @@ local function createExceptionObject(this)
124135 return this .exception
125136end
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
141139local nextTaskId = 1
142140local currentTask
143141local completedTask
@@ -157,58 +155,22 @@ local function getId(this)
157155 return id
158156end
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-
182158local function isCompleted (this )
183159 local status = this .status
184160 return status == TaskStatusRanToCompletion or status == TaskStatusFaulted or status == TaskStatusCanceled
185161end
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-
197163local function fromResult (result )
198164 return setmetatable ({ status = TaskStatusRanToCompletion , data = result }, Task )
199165end
200166
201- Task .FromResult = fromResult
202-
203167local function fromCanceled (cancellationToken )
204168 if cancellationToken and cancellationToken :getIsCancellationRequested () then
205169 throw (ArgumentOutOfRangeException (" cancellationToken" ))
206170 end
207171 return setmetatable ({ status = TaskStatusCanceled , data = cancellationToken }, Task )
208172end
209173
210- Task .FromCanceled = fromCanceled
211-
212174local function getCompletedTask ()
213175 local t = completedTask
214176 if t == nil then
@@ -218,8 +180,6 @@ local function getCompletedTask()
218180 return t
219181end
220182
221- Task .getCompletedTask = getCompletedTask
222-
223183local 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 )
258218end
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-
300220local function getContinueActions (task )
301221 local continueActions = task .continueActions
302222 if continueActions == nil then
@@ -306,24 +226,6 @@ local function getContinueActions(task)
306226 return continueActions
307227end
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-
327229local function await (t , task )
328230 assert (t .co )
329231 local continueActions = getContinueActions (task )
@@ -352,22 +254,112 @@ local function await(t, task)
352254 end
353255end
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
372364local taskCoroutinePool = {}
373365local function taskCoroutineCreate (t , f )
409401
410402function System .async (f , ...)
411403 return async (f , nil , ... )
412- end
404+ end
0 commit comments