Tcl Library Source Code

Changes On Branch bug-td-coroutine
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch bug-td-coroutine Excluding Merge-Ins

This is equivalent to a diff from 7bed475cb2 to 5f50c249bd

2014-04-11
20:26
Ticket [c21b57e4fc]. Fixed version number mismatch for "coroutine". See also Ticket [ac8d016077] whose fix (revision [7bed475cb2]) introduced the problem. check-in: 51083f878a user: andreask tags: trunk
2014-03-26
17:29
In coroutine and coro_auto: 'read' must correctly emulate Tcl's built-in read and not close the chan at EOF. Add command expansion in 'global', which looks like it never worked. Took the opportunity to fix how 'global' stores coro-global values so that we don't tramp on Frame #1's local variables (no compatibility break as 'global' never worked). Bumped versions. Adding tests. Work-in-progress. Leaf check-in: 5f50c249bd user: twylite tags: bug-td-coroutine
2014-03-24
18:24
Ticket [ac8d016077]. Package coroutine and coroutine::auto. Fixed missing variable "result" in various ok code paths. Bumped versions to 1.1.1 and 1.1.2 respectively. check-in: 7bed475cb2 user: andreask tags: trunk
18:03
Ticket 874dedb816 - struct::matrix - Fixed documentation buglet. check-in: ed580c5543 user: andreask tags: trunk

Changes to modules/coroutine/ChangeLog.














1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+
+
+
+
+
+
+
+
+
+
+
+
+







2014-03-24  Trevor Davel  <[email protected]>

	* coroutine.tcl: Stopped 'read' closing the channel at EOF, which is 
	* coro_auto.tcl: not the behaviour's of Tcl's built-in read.  Bumped
	  versions to 1.1.3.        
	* pkgIndex.tcl: Updated version numbers.

2014-03-24  Andreas Kupries  <[email protected]>

	* coroutine.tcl: Fixed missing variable "result" in various ok code
	* coro_auto.tcl: paths. Bumped versions to 1.1.1 and 1.1.2 
	  respectively

2013-05-31  Andreas Kupries  <[email protected]>

	* coroutine.tcl: Added Colin Macleod and http://wiki/21555
	* coro_auto.tcl: to the set of acknowledged contributors
	  and references for the module.

2013-05-15  Andreas Kupries  <[email protected]>

Changes to modules/coroutine/coro_auto.tcl.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







## -- Tcl Module -- -*- tcl -*-
# # ## ### ##### ######## #############

# @@ Meta Begin
# Package coroutine::auto 1.1.2
# Package coroutine::auto 1.1.3
# Meta platform        tcl
# Meta require         {Tcl 8.6}
# Meta require         {coroutine 1.1}
# Meta license         BSD
# Meta as::author      {Andreas Kupries}
# Meta as::origin      http://wiki.tcl.tk/21555
# Meta summary         Coroutine Event and Channel Support
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
222
223
224
225
226
227
228

229
230
231
232
233
234
235







-







		yield
		::chan event $chan readable {}
	    } else {
		::chan configure $chan -blocking $blocking
		append buf $result

		if {[::chan eof $chan]} {
		    ::chan close $chan
		    break
		}
	    }
	}
    } else {
	# Loop until total characters have been read, or eof found,
	# whichever is first.
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
252
253
254
255
256
257
258

259
260
261
262
263
264
265







-







		::chan event $chan readable {}
	    } else {
		::chan configure $chan -blocking $blocking
		append buf $result
		incr   left -[string length $result]

		if {[::chan eof $chan]} {
		    ::chan close $chan
		    break
		} elseif {!$left} {
		    break
		}
	    }
	}
    }
306
307
308
309
310
311
312
313

314
304
305
306
307
308
309
310

311
312







-
+


    return
} ::coroutine::auto}

# # ## ### ##### ######## #############
## Ready

package provide coroutine::auto 1.1.2
package provide coroutine::auto 1.1.3
return

Changes to modules/coroutine/coroutine.tcl.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







## -- Tcl Module -- -*- tcl -*-
# # ## ### ##### ######## #############

# @@ Meta Begin
# Package coroutine 1.1.1
# Package coroutine 1.1.3
# Meta platform        tcl
# Meta require         {Tcl 8.6}
# Meta license         BSD
# Meta as::author      {Andreas Kupries}
# Meta as::author      {Colin Macleod}
# Meta as::author      {Colin McCormack}
# Meta as::author      {Donal Fellows}
86
87
88
89
90
91
92
93

94
95

96
97
98
99
100
101
102
86
87
88
89
90
91
92

93
94

95
96
97
98
99
100
101
102







-
+

-
+







proc ::coroutine::util::global {args} {
    # Frame #1 is the coroutine-specific stack frame at its
    # bottom. Variables there are out of view of the main code, and
    # can be made visible in the entire coroutine underneath.

    set cmd [list upvar "#1"]
    foreach var $args {
	lappend cmd $var $var 
	lappend cmd COROGLOBAL($var) $var 
    }
    tailcall $cmd
    tailcall {*}$cmd
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::after {delay} {
    ::after $delay [info coroutine]
    yield
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
259
260
261
262
263
264
265

266
267
268
269
270
271
272







-







		yield
		::chan event $chan readable {}
	    } else {
		::chan configure $chan -blocking $blocking
		append buf $result

		if {[::chan eof $chan]} {
		    ::chan close $chan
		    break
		}
	    }
	}
    } else {
	# Loop until total characters have been read, or eof found,
	# whichever is first.
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
289
290
291
292
293
294
295

296
297
298
299
300
301
302







-







		::chan event $chan readable {}
	    } else {
		::chan configure $chan -blocking $blocking
		append buf $result
		incr   left -[string length $result]

		if {[::chan eof $chan]} {
		    ::chan close $chan
		    break
		} elseif {!$left} {
		    break
		}
	    }
	}
    }
369
370
371
372
373
374
375
376

377
367
368
369
370
371
372
373

374
375







-
+

namespace eval ::coroutine::util {
    #checker exclude warnShadowVar
    variable counter 0
}

# # ## ### ##### ######## #############
## Ready
package provide coroutine 1.1.1
package provide coroutine 1.1.3
return

Added modules/coroutine/coroutine.test.

























































































































1
2
3
4
5
6
7
8
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
119
120
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# coroutine.test
#
# Tests for the coroutine package
#
# Copyright (C) 2014 Trevor Davel <[email protected]>
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------

package require tcltest

source [file join \
    [file dirname [file dirname [file join [pwd] [info script]]]] \
    devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2.3

testing {
    useLocal coroutine.tcl coroutine ::coroutine::util
}


# ----- Helpers ----------------------------------------------------------------

  
  # Resume a coroutine in a tight loop and collect its output as a list.  When
  # the coroutine terminates return the list. 
  proc Test_collect {coro} {
    set coro [uplevel 1 [list namespace which -command $coro]]
    set result {}
    while { [info commands $coro] ne {} } {
      lappend result [$coro] 
    }
    set result
  }
  

# ----- coroutine::util::create ------------------------------------------------

  # coroutine::util::create should create a coroutine with a unique name

  test coroutine-1.1 {coroutine::util::create} -body {
    set coroid [namespace eval ::coroutine::util {
      create apply {{} {
        yield [info coroutine]
        yield "alpha"
        return "beta"
      }}
    }]
    Test_collect $coroid
  } -result {alpha beta}
  

# ----- coroutine::util::global ------------------------------------------------

  # coroutine::util::global should link to a coro-global variable, not an
  # interp-global variable.  It should work at all stack levels _including
  # the first frame of the coroutine_, should not tramp on the first frame's
  # local vars, and should be auto-created if necessary by commands like 
  # [incr]/[append] (from any stack level).  [global] can be called with
  # multiple variable names.

  proc ::coroutine::util::Test_global {} {
    global myglobal
    incr myglobal
    yield $::myglobal 
    yield $myglobal
    return [apply [list {} {
      global strglobal myglobal
      incr myglobal
      yield $::myglobal 
      yield $myglobal
      return [append strglobal "ghi"]      
    } [namespace current]]] 
  }
  
  test coroutine-2.1 {coroutine::util::global} -body {
    set myglobal 10
    set strglobal "abc"

    set coroid [namespace eval ::coroutine::util {
      create apply [list {} {
        yield [info coroutine]
        global myglobal
        incr myglobal            ;# Create coro-global that doesn't exist yet
        yield $::myglobal        ;# Dereference interp/real global
        yield $myglobal          ;# Dereference coro-global 
        return [apply [list {} { ;# Push another stack frame
          global myglobal strglobal
          incr myglobal
          append strglobal "def"
          yield $::myglobal
          yield $myglobal
          yield $::strglobal
          yield $strglobal
          return [Test_global]   ;# And another two stack frames, one is named
        } [namespace current]]]  ;# All the coro's stack frames must have access
      } [namespace current]]     ;# to the overridden [global] command
    }]
    Test_collect $coroid
  } -result {10 1 10 2 abc def 10 3 10 4 defghi}

  catch { unset myglobal }


# ----- coroutine::util::after -------------------------------------------------


  # Work in progress
  # - coroutine::util::global functionality has been slightly modified in 
  #   order to work correctly at frame #1.  This may need to be reviewed.
  #   The new approach prevents tramping on frame #1's local variables.
  #   If trampling is intended then we may need a workaround to detect use of
  #   'global' in frame #1 and make it a noop. 
  # - Run tests with: %TCLSH% sak.tcl test run coroutine

testsuiteCleanup
return

Changes to modules/coroutine/pkgIndex.tcl.

1
2
3


1


2
3

-
-
+
+
if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded coroutine       1.1   [list source [file join $dir coroutine.tcl]]
package ifneeded coroutine::auto 1.1.1 [list source [file join $dir coro_auto.tcl]]
package ifneeded coroutine       1.1.3 [list source [file join $dir coroutine.tcl]]
package ifneeded coroutine::auto 1.1.3 [list source [file join $dir coro_auto.tcl]]