JPEG Tools

Diff
Login

Diff

Differences From Artifact [6f3a26e84c]:

To Artifact [99fb4c8fd3]:


9
10
11
12
13
14
15
16
17


18
19
20
21
22
23

24
25

26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113
114
115
116
117
118
9
10
11
12
13
14
15


16
17
18
19
20
21
22

23


24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
-
+
+





-
+
-
-
+












-
+









-
+










-
+







-
+







-
+







-
+







-
+













-
+





-
+







## defered through the event-loop.
#
## Programing with futures is explicit continuation-passing-style.

# ### ### ### ######### ######### #########
## Requisites

package require Debug
package require Debug::snit
package require debug
package require debug::caller
package require snit

# ### ### ### ######### ######### #########
## Narrative tracing

Debug off    future
debug level  future
#Debug on     future
Debug prefix future {[list [Debug::snit::call]] }
debug prefix future {[debug caller] | }

# ### ### ### ######### ######### #########
## Implementation

snit::type future {
    # ### ### ### ######### ######### #########
    ## Class API
    ## Simplified construction with integrated setup

    # Provide new future configured with arguments. See `on ..`,
    # `nop`, `empty`, and `chain`.
    typemethod new {args} {
	Debug.future {}
	debug.future {}
	set future [$type create %AUTO%]
	if {[llength $args]} { $future {*}$args }
	return $future
    }

    # Provide a new future in default configuration and trigger it to
    # return the args and the next idle point. Further configuration
    # can be done on the result object.
    typemethod return {args} {
	Debug.future {}
	debug.future {}
	set f [$type new]
	after idle [list $f return {*}$args]
	return $f
    }

    # ### ### ### ######### ######### #########
    ## API. Various configuration methods. Chainable.

    # Configure callback to invoke on `return`.
    method {on return} {cmdprefix args} {
	Debug.future {}
	debug.future {}
	set myOkCmdPrefix $cmdprefix
	if {[llength $args]} { $self {*}$args }
	return $self
    }

    # Configure callback to invoke on `error`.
    method {on error} {cmdprefix args} {
	Debug.future {}
	debug.future {}
	set myErrorCmdPrefix $cmdprefix
	if {[llength $args]} { $self {*}$args }
	return $self
    }

    # Clear all callbacks. The future will now swallow all its invokations.
    method nop {} {
	Debug.future {}
	debug.future {}
	set myOkCmdPrefix    {}
	set myErrorCmdPrefix {}
	return
    }

    # Same as nop.
    method empty {} {
	Debug.future {}
	debug.future {}
	set myOkCmdPrefix    {}
	set myErrorCmdPrefix {}
	return
    }

    # Configure callbacks to post invokations to the other future.
    method chain {future args} {
	Debug.future {}
	debug.future {}
	# Inlined on return on error configuration chaining to another
	# future.

	set myOkCmdPrefix    [list $future return]
	set myErrorCmdPrefix [list $future error]
	if {[llength $args]} { $self {*}$args }
	return $self
    }

    # ### ### ### ######### ######### #########
    ## API. Invoke the future. This will destroy the instance as well.

    method error {message} {
	Debug.future {}
	debug.future {}
	$self Error $message
	return
    }

    method return {args} {
	Debug.future {}
	debug.future {}
	# Syntax:             | 0
	#       : -code x     | 2
	#       : -code x val | 3
	#       :         val | 4
	# Allowing multiple -code settings, last one is taken.

	set rcode  0
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192







-
+

















-
+










-
+










+








    # ### ### ### ######### ######### #########
    ## Destruction. A user is not allowed to destroy instances. Can
    ## only be done by invoking it (return or error), as part of which
    ## it destroys itself.

    destructor  {
	Debug.future {}
	debug.future {}
	if {$myIsDone} return
	return -code error "Illegal attempt to destroy unresolved future \"$self\""
    }

    # ### ### ### ######### ######### #########
    ## State

    variable myIsDone         0
    variable myOkCmdPrefix    {return -code return}
    variable myErrorCmdPrefix {return -code error}

    # ### ### ### ######### ######### #########
    ## Helper commands. Invoke the configured callbacks, if any. This
    ## is also where the instance destroys itself. Note that callback
    ## execution is defered to the event loop.

    method Ok {result} {
	Debug.future {[list ==> $myOkCmdPrefix]}
	debug.future {[list ==> $myOkCmdPrefix]}

	set cmdprefix $myOkCmdPrefix
	DestroySelf

	if {![llength $cmdprefix]} return
	after 0 [list {*}$cmdprefix $result]
	return
    }

    method Error {message} {
	Debug.future {[list ==> $myErrorCmdPrefix]}
	debug.future {[list ==> $myErrorCmdPrefix]}

	set cmdprefix $myErrorCmdPrefix
	DestroySelf

	if {![llength $cmdprefix]} return
	after 0 [list {*}$cmdprefix $message]
	return
    }

    proc DestroySelf {} {
	debug.future {}
	upvar 1 self self myIsDone myIsDone
	set myIsDone 1
	$self destroy
	return
    }

    ##