( u -- )

Display block u in an implementation-defined format. Store u in SCR.



mcondronavatar of mcondron [108] Does LIST transfer data to any buffer?Request for clarification2019-08-11 15:53:04

I just want to get clear whether LIST moves data from the block into any buffer, or just displays it without doing anything to any block buffer. The description seems to imply it displays only, without changing the contents of any buffer. Just want to be sure.

AntonErtlavatar of AntonErtl

7.2 says:

The current block buffer is the block buffer most recently accessed by BLOCK, BUFFER, LOAD, LIST, or THRU.

This implies that LIST loads the block into a buffer if it is not there already. Also, if you consider that these words were devised for use on bare metal where you have to transfer a complete sector, it is clear that you need to load at least one sector into a buffer.

Interestingly, 7.3.2 mentions conditions that can invalidate a block buffer, but does not mention LOAD, LIST, and THRU. The committee may have considered that these words implicitly call BLOCK, but given that this is not mentioned for these words, this is probably an unintentional omission.

JennyBrienavatar of JennyBrien

I also don't see any requirement that a system have more than one buffer, so that a straight block-to-block transfer would be guaranteed to work

e.g : BCOPY ( blk1 blk2 -- copy contents of block1 to block2 ) SWAP BLOCK SWAP BLOCK 1024 MOVE UPDATE ;

If there is only one buffer, the second call to BLOCK will overwrite the first.

MitchBradleyavatar of MitchBradley

The intention was that BLOCK works in the historical way. In historical systems, LOAD, LIST, THRU, and in fact everything that accesses blocks in any way used BLOCK and hence changed the block buffer cache. It has always been a usage requirement that you can't depend on holding pointers to previous calls to BLOCK "for long". To the extent that the standard fails to make all that explicit and misses some invalidation cases, it is an omission.

The committee didn't spend much time on BLOCK; it was seen as a "dead horse" and we had much to do on other fronts. So I'm not surprised that we missed some stuff. The new stuff was argued and nit-picked until we were exhausted, but the BLOCK stuff just sorta slid in with the expectation that anybody using it was already so familiar with it that they knew what to expect, and then it would die a gradual death.

Regarding the number of buffers: I don't recall ever having seen a system with only one block buffer. The need to copy one to another pretty much makes a one-buffer implementation impractical. The standard should make that explicit. Or better yet, get rid of BLOCK entirely, which was my preference during the initial deliberations. The "lifetime of a block pointer" issue is just too problematic for modern systems. (That said, I did actually use BLOCK as a factor inside some of my filesystem implementations - but it was a private implementation that was used only inside the filesystem, so the characteristics and usage patterns were controlled.)

AntonErtlavatar of AntonErtl

A block-to-block copy is not guaranteed to work even if more than one buffer exists, because the second call to BLOCK (or one would rather use BUFFER) invalidates the address returned by the first call to BLOCK; and I don't see a way to do it as a standard program without copying to an intermediate place. In practice, one would probably do it in a zero-copy way by writing back the buffer to its original block if it was updated, then changing its number to the new block, and marking it as modified with UPDATE. This is not possible in the standard, though.

Concerning a one-buffer implementation: My original implementation of the block wordset for Gforth was a minimal implementation and used just one buffer. It has been replaced with a more sophisticated multi-buffer implementation later.

Reply New Version