method connect {} {
set conn_fh [open {|object-remote-node} r+]
- set firstline [gets conn_fh]
+ set firstline [gets $conn_fh]
switch $firstline {
Shere {}
default { error "Expected Shere, got $firstline" }
return $conn
}
-}
+}
+
+snit::type ten::connection {
+
+ option -send_to_fh
+ option -read_channel
+
+ constructor {args} {
+ $self configurelist $args
+ fconfigure $options(-send_to_fh) -buffering none
+ $options(-read_channel) configurelist [list \
+ -on_line_call [ mymethod Receive ] \
+ -on_close_call [ mymethod ChannelClosed ] \
+ ]
+ }
+
+ method Receive {$line} {
+ puts $line
+ }
+
+ method ChannelClosed {} {
+ error "Fail"
+ }
+
+ method send {message_type args} {
+ set future [ten::future %AUTO%]
+ set call_args [concat $message_type $future $args]
+ }
+}
+
+snit::type ten::future {
+
+ variable callbacks
+ variable is_ready 0
+ variable result ""
+ variable failure ""
+
+ method done {args} {
+ if [$self is_ready] {
+ error "Future $self already completed"
+ }
+ set result $args
+ $self MarkReady
+ }
+
+ method fail {args} {
+ if [$self is_ready] {
+ error "Future $self already completed"
+ }
+ set failure $args
+ $self MarkReady
+ }
+
+ method on_ready {cb_code} {
+ lappend callbacks [list ready $cb_code]
+ }
+
+ method on_done {cb_code} {
+ lappend callbacks [list done $cb_code]
+ }
+
+ method on_fail {cb_code} {
+ lappend callbacks [list fail $cb_code]
+ }
+
+ method MarkReady {} {
+ set is_ready 1
+ foreach cb $callbacks {
+ set cb_type [lindex $cb 0]
+ set cb_code [lindex $cb 1]
+ switch $cb_type {
+ ready { eval [concat $cb_code $self] }
+ done {
+ if ![$self is_failure] {
+ eval [concat $cb_code [list $result]]
+ }
+ }
+ failed {
+ if [$self is_failure] {
+ eval [concat $cb_code [list $failure]]
+ }
+ }
+ }
+ }
+ }
+
+ method AssertReady {} {
+ if {!$is_ready} {
+ error "Future not ready"
+ }
+ }
+
+ method is_ready {} { return $is_ready }
+
+ method get {} {
+ $self AssertReady
+ if [$self is_failure] {
+ error $failure
+ }
+ return $result
+ }
+
+ method is_failure {} {
+ $self AssertReady
+ if [llength $failure] {
+ return 1
+ }
+ return 0
+ }
+
+ method failure {} {
+ $self AssertReady
+ return $failure
+ }
+
+ method await {} {
+ vwait "${selfns}::is_ready"
+ }
+}
snit::type ten::read_channel {
option -fh
}
}
-package provide ten 0.0.01
+package provide ten 0.0.1