347347
348348--- @alias runner.info { target ?: parser.object , loc : parser.object }
349349
350- --- @type thread ?
351- local masterRunner = nil
352- --- @type table<thread , runner.info>
353- local runnerInfo = setmetatable ({}, {
354- __mode = ' k' ,
355- __index = function (self , k )
356- self [k ] = {}
357- return self [k ]
358- end
359- })
360- --- @type linked-table ?
361- local runnerList = nil
362-
363- --- @async
364- --- @param info runner.info
365- local function waitResolve (info )
366- while true do
367- if not info .target then
368- break
369- end
370- if info .target .node == info .loc then
371- break
372- end
373- local node = vm .getNode (info .target )
374- if node and node .resolved then
375- break
376- end
377- coroutine.yield ()
378- end
379- info .target = nil
380- end
381-
382- local function resolveDeadLock ()
383- if not runnerList then
384- return
385- end
386-
387- --- @type runner.info[]
388- local infos = {}
389- for runner in runnerList :pairs () do
390- local info = runnerInfo [runner ]
391- infos [# infos + 1 ] = info
392- end
393-
394- table.sort (infos , function (a , b )
395- local uriA = guide .getUri (a .loc )
396- local uriB = guide .getUri (b .loc )
397- if uriA ~= uriB then
398- return uriA < uriB
399- end
400- return a .loc .start < b .loc .start
401- end )
402-
403- local firstTarget = infos [1 ].target
404- --- @cast firstTarget -?
405- local firstNode = vm .setNode (firstTarget , vm .getNode (firstTarget ):copy (), true )
406- firstNode .resolved = true
407- firstNode :setData (' resolvedByDeadLock' , true )
408- end
409-
410350--- @async
411351--- @param loc parser.object
412352--- @param start fun ()
@@ -418,57 +358,6 @@ function vm.launchRunner(loc, start, finish, callback)
418358 return
419359 end
420360
421- local function resumeMaster ()
422- for i = 1 , 10010 do
423- if not runnerList or runnerList :getSize () == 0 then
424- return
425- end
426- local deadLock = true
427- for runner in runnerList :pairs () do
428- local info = runnerInfo [runner ]
429- local waitingSource = info .target
430- if coroutine.status (runner ) == ' suspended' then
431- local suc , err = coroutine.resume (runner )
432- if not suc then
433- log .error (debug.traceback (runner , err ))
434- end
435- else
436- runnerList :pop (runner )
437- deadLock = false
438- end
439- if not waitingSource or waitingSource ~= info .target then
440- deadLock = false
441- end
442- end
443- if runnerList :getSize () == 0 then
444- return
445- end
446- if deadLock then
447- resolveDeadLock ()
448- end
449- if i == 10000 then
450- local lines = {}
451- lines [# lines + 1 ] = ' Dead lock:'
452- for runner in runnerList :pairs () do
453- local info = runnerInfo [runner ]
454- lines [# lines + 1 ] = ' ==============='
455- lines [# lines + 1 ] = string.format (' Runner `%s` at %d(%s)'
456- , info .loc [1 ]
457- , info .loc .start
458- , guide .getUri (info .loc )
459- )
460- lines [# lines + 1 ] = string.format (' Waiting `%s` at %d(%s)'
461- , info .target [1 ]
462- , info .target .start
463- , guide .getUri (info .target )
464- )
465- end
466- local msg = table.concat (lines , ' \n ' )
467- log .error (msg )
468- end
469- end
470- end
471-
472361 local function launch ()
473362 start ()
474363 if not loc .ref then
@@ -499,67 +388,5 @@ function vm.launchRunner(loc, start, finish, callback)
499388 finish ()
500389 end
501390
502- local co = coroutine.create (launch )
503- locNode :setData (' runner' , co )
504- local info = runnerInfo [co ]
505- info .loc = loc
506-
507- if not runnerList then
508- runnerList = linked ()
509- end
510- runnerList :pushTail (co )
511-
512- if not masterRunner then
513- masterRunner = coroutine.running ()
514- resumeMaster ()
515- masterRunner = nil
516- return
517- end
518- end
519-
520- --- @async
521- --- @param source parser.object
522- function vm .waitResolveRunner (source )
523- local myNode = vm .getNode (source )
524- if myNode and myNode .resolved then
525- return
526- end
527-
528- local running = coroutine.running ()
529- if not masterRunner or running == masterRunner then
530- return
531- end
532-
533- local info = runnerInfo [running ]
534-
535- local targetLoc
536- if source .type == ' getlocal' then
537- targetLoc = source .node
538- elseif source .type == ' local'
539- or source .type == ' self' then
540- targetLoc = source
541- info .target = info .target or source
542- else
543- error (' Unknown source type: ' .. source .type )
544- end
545-
546- local targetNode = vm .getNode (targetLoc )
547- if not targetNode then
548- -- Wait for compiling local by `compiler`
549- return
550- end
551-
552- waitResolve (info )
553- end
554-
555- --- @param source parser.object
556- function vm .storeWaitingRunner (source )
557- local sourceNode = vm .getNode (source )
558- if sourceNode and sourceNode .resolved then
559- return
560- end
561-
562- local running = coroutine.running ()
563- local info = runnerInfo [running ]
564- info .target = source
391+ launch ()
565392end
0 commit comments