diff -ur a/thr.py b/thr.py --- a/thr.py 2020-10-29 22:38:06.000000000 +0900 +++ b/thr.py 2020-11-01 00:02:09.000000000 +0900 @@ -90,31 +90,105 @@ return empty.to_attr( e, locals() ) +def stat_lst_new(): + lst = [] + lock = lock_new() + + def add(stat): + if stat not in lst: + lock.on() + lst.append( stat ) + lock.off() + def rm(stat): + if stat in lst: + lock.on() + lst.remove( stat ) + lock.off() + + def gc(): + for stat in lst[ : ]: + stat.gc() + + def quit(tmout=None): + for stat in lst[ : ]: + stat.quit( tmout ) + + return empty.new( locals() ) + +stat_lst = stat_lst_new() + +def stat_new(th): + e = empty.new() + e.v = None + stop_ev = event_new() + + def set(s): + e.v = s + + def set_run(): + set( 'run' ) + stat_lst.add( e ) + + def set_stop(): + set( 'stop' ) + stop_ev.set() + + def set_joined(): + stat_lst.rm( e ) + set( 'joined' ) + + is_stat = lambda s: e.v == s + is_run = lambda : is_stat( 'run' ) + is_stop = lambda : is_stat( 'stop' ) + wait_stop = lambda tmout=None: stop_ev.wait( tmout ) + + def gc(): + if is_stop(): + th.join() + + def quit(tmout=None): + if is_run(): + th.quit_ev.set() + if wait_stop( tmout ): + gc() + + return empty.add( e, locals() ) + + def th_new(target=None, args=(), gc=None): e = empty.new() quit_ev = threading.Event() th = None + stat = stat_new( e ) def func(*args): if e.target: + stat.set_run() e.target( *e.args ) + stat.set_stop() if gc: gc.put( e ) def start(): + stat_lst.gc() e.th = threading.Thread( target=func, args=e.args ) e.th.daemon = True e.th.start() if gc: gc.lst.add( e ) - def join(): + def join(tmout=None): if e.th: + if tmout != None: + if not stat.wait_stop( tmout ): + return # ! e.th.join() + stat.set_joined() if gc: gc.lst.rm( e ) - def stop(): + def stop(tmout=None): quit_ev.set() - join() + join( tmout ) + stat_lst.gc() return empty.to_attr( e, locals() )