Posted to tcl by Poor Yorick at Wed Feb 09 18:29:11 GMT 2022view pretty

proc waitforstuff {} {
	set elapsed [expr {entier(rand() * 2000)}]
	after $elapsed [list [info coroutine]]
	yield
}


proc worker {spec body args} {
	coroutine [info cmdcount] apply [list $spec $body] {*}$args
}


proc collect countvar {
	upvar $countvar count
	lassign [return -level 0 {*}[
		yieldto lindex [list [info coroutine]]]] url
	return $url
}


proc done {} {
	variable status
	puts {Zipped and sent!}
	set status 0
}


proc download {dir url callback} {
	worker {dir url callback} {
		catch {
			puts [list downloading $url]
			waitforstuff
			set content [list content of $url]
			if {$url eq {two}} {
				error {not two!}
			}
			save_file $dir $url $content
			lindex $url
		} cres copts
		dict set copts args [list $dir $url]
		{*}$callback -options $copts $cres
	} $dir $url $callback
}


proc downloads {dir urls} {
	set length [llength $urls]
	foreach url $urls {
		after 0 [
			list download $dir $url [list [info coroutine]]]
	}
	set errors {}
	while {[incr length -1] >= 0} {
		if {[catch {collect length} cres copts]} {
			if {[dict exists $copts args]} {
				puts [list error on $dir $url]
			}
			lappend errors $cres $copts
		}
	}
	return
}


proc save_file {dirvar url content} {
	namespace upvar [namespace current] $dirvar dir
	puts [list saving to dir $dirvar]
	dict set dir $url $content
}


proc zip dirvar {
	namespace upvar [namespace current] $dirvar dir
	waitforstuff
	foreach {key value} $dir {
		puts [list $key $value]
	}
}


proc mail {} {
	puts [list mailed stuff]
}



proc main_coro {argv0 argv} {
	yield [list [info coroutine]]
	set dir mydir
	set urls {one two three}
	downloads $dir $urls
	zip $dir
	mail
	done
}


after 0 [coroutine main main_coro $argv0 $argv]