Tcl Source Code

Artifact [9371e1dabc]
Login

Artifact 9371e1dabcc51af56da237b3e01a585dbbc0f18f:

Attachment "wr.tcl" to ticket [2176669fff] added by andreas_kupries 2009-11-21 02:48:01.

# Here is a small example how Tcl is not maintaining the virtual seek
# location in the presence of unflushed output.

set  fd [open testfile r+]	; # (0)
puts [tell $fd]                 ; # (1) == 0
puts -nonewline $fd Z           ; # (2)
puts [read $fd 2]               ; # (3)
puts [tell $fd]                 ; # (4) == -1, error
exit

# (1) open file, location at 0.
#
# (2) Write single byte.
#     Tcl buffers 1 byte for output.
#     Tcl's file location is 0! Would be 1 after a flush.
#
# (3) The read bytes come from locations 0 and 1, see above. Note (*).
#     Tcl read 4096 bytes (default -buffersize), a delivered 2
#     => OS'   location = 4096
#     => Buffered 4094 bytes
#     => Tcl's location = 2
#
# (4) [tell] is (in essence) [seek 0 current], i.e. move nothing, at
#     the current location, and return new location. What it doesn't
#     do is flushing the out. It takes input/output buffering into
#     account to go from OS location to Tcl's location.
#
#     As we have both input and output buffered we got -1, error.
#
#     What if the check is disabled. Then we get 2.
#
#     Because that is what we have read, starting from location 0.
#
#     However, we have unflushed data pending for write, which now has
#     an _indeterminate_ location. It was likely intended to be at
#     location 0, but due to the intervening read it would end up at
#     location 2 if flushed now.
#
#     The main thing, [read] is not accounting for buffered
#     output when it determines from where to read in the channel.
#
#     OTOH, if it were doing so a read operation may write to the
#     channel (flush). This is not good for an operation supposed to
#     'query' the channel only, not modify it.
#
#     The upshot is that having buffered input and output is a signal
#     that Tcl cannot really determine a proper location in the file
#     any longer, because of this "read after buffered/unflushed write".
#
# (*) See maketestfile.tcl, the file contains a pattern of chars
#     which allows us to tell the location from the chars themselves,
#     instead of asking Tcl