Posted to tcl by aspect at Mon May 28 14:07:55 GMT 2018view pretty

package require Thread

proc go {args} {coroutine go#[info cmdcount] {*}$args}
proc yieldm {val} {yieldto string cat $val}

proc asocket {args} {
    set t [thread::create]

    thread::send $t [list set args $args]
    thread::send $t [list set tid [thread::id]]
    thread::send $t [list set callback [info coroutine]]

    thread::send -async $t {
        set rc [catch {socket {*}$args} res opts]
        if {$rc == 0} {thread::transfer $tid $res}              ;# on success, pass the chan back
        thread::send $tid [list {*}$callback $rc $res $opts]    ;# send back the result, including error code
        thread::exit
    }

    lassign [yieldto string cat] rc res opts    ;# wait for a result
    return -code $rc {*}$opts $res              ;# return a socket or error
}

proc connect {args} {
    puts "connecting to $args"
    try {
        set sock [asocket {*}$args]
        puts "connected to $args: $sock"
        close $sock
    } on error {e} {
        puts "connect error $args: $e"
    }
}

proc main {args} {
    foreach {host port} $args {
        go connect $host $port          ;# spawn a coro for each connection
    }
}

proc watch {ms args} {
    set threads {}
    while 1 {
        set r [{*}$args]
        if {$r ne $threads} {
            set threads $r
            puts "Threads: $threads"
        }
        after $ms [info coroutine]
        yield
    }
}

go watch idle thread::names
coroutine Main main {*}$::argv
vwait forever

# $ tclsh sockinthread.tcl abc.net.au 80 www.tcl.tk 80 localhost 80 ghhg.deokde 123
# Threads: tid0x7f8b1734f680
# connecting to abc.net.au 80
# connecting to www.tcl.tk 80
# connecting to localhost 80
# connecting to ghhg.deokde 123
# connect error localhost 80: couldn't open socket: connection refused
# Threads: tid0x7f8b029dc700 tid0x7f8b031dd700 tid0x7f8b03fff700 tid0x7f8b091fd700 tid0x7f8b1734f680
# Threads: tid0x7f8b029dc700 tid0x7f8b03fff700 tid0x7f8b091fd700 tid0x7f8b1734f680
# connect error ghhg.deokde 123: couldn't open socket: Name or service not known
# Threads: tid0x7f8b03fff700 tid0x7f8b091fd700 tid0x7f8b1734f680
# connected to www.tcl.tk 80: sock7f8afc065fb0
# Threads: tid0x7f8b091fd700 tid0x7f8b1734f680
# connected to abc.net.au 80: sock7f8b0405c010
# Threads: tid0x7f8b1734f680