On Fri, 25 Apr 2008, Szakáts Viktor wrote:
> I used 5.2 for this comparison.
> I've now tried with 5.3 which behaves differently
> in a few places, but overall I cannot easily see
> improvements over 5.2, at least not in these tests.
If you want to see the difference add few additional rows
two the table and test sth like:
TEST_CALL( o:goTop() )
TEST_CALL( o:forceStable() )
TEST_CALL( o:down() )
TEST_CALL( o:forceStable() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:forceStable() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:forceStable() )
TEST_CALL( o:pageDown() )
TEST_CALL( o:forceStable() )
BTW I changed a little bit your code for easier comparison the results
with diff. I'm attaching it.
As I can see the differences are not such huge. There are in fact
three differences:
1. dividing :stable() steps
I decided that only one position repositioning is allowed in one
step and looks like Clipper makes some screen/internal parameters
updates in separated steps. It probably can be tuned to make it
similar to Clipper though it's not very important.
2. after :goTop() and :goBottom Clipper repeats the forward skipping
test in the 1-st call to :stablize(). In this test internal :rosPos
is not yet update and it later causes some small differences in
repositioning. It's exactly the same what CL5.3 makes for _ALL_
forward repositioning I was writing about.
It can be replicated but with the cost of performance and in fact
it does not guaranties that it will be good protection for concurrent
access. It's a race condition which cannot be resolved. It can be
reduced later inside record movement for update but this part seems
to be missing in Clipper so I guess it was rather workaround for
concurrent access added to already existed code which probably comes
from S87 or even earlier Clipper versions. In CL52 it was added only
in few places but in CL53 in practice to all forward skips. Probably
it was easier to add such hack instead of updating repositioning code
and make it safe for concurrent modifications in source data. These
forward skip tests only reduce the time when sth wrong may happen
but they not eliminate the race condition. I strongly prefer to update
repositioning code and fully respect value returned from user skip
block in all places.
3. Mixed direct (:rowPos:=<x>/:goTop()/:goBottom()) and relative
(:up()/:down()/:pageUp()/...) repositioning. In such case the
results can be really strange. It was not easy to detect the
exact rule when I was checking it few days ago but I haven't made
careful and deep tests. I do not know if it worth to invest time
for sth what probably will not effect 99.9% of code.
best regards,
Przemek
STATIC s_nCount := 0
STATIC s_cCurrBlock := ""
STATIC s_cResult1
STATIC s_cResult2
#translate TEST_CALL( <x> ) => TEST_C_CALL( o, #<x>, {|| <x> } )
FUNCTION Main()
LOCAL o
LOCAL nOldRecNo
LOCAL tmp
// AltD()
dbCreate( "_test", {{ "ID", "C", 10, 0 }} )
USE _test NEW EXCLUSIVE ALIAS w_TEST
dbAppend() ; w_TEST->ID := "01"
dbAppend() ; w_TEST->ID := "02"
dbAppend() ; w_TEST->ID := "03"
dbAppend() ; w_TEST->ID := "04"
o := TBrowseNew( 0, 0, 6, 8 )
o:GoTopBlock := { || nOldRecNo := RecNo(), dbGoTop(), my_QOut( o, {
"TOP", RecNo(), nOldRecNo } ) }
o:GoBottomBlock := { || nOldRecNo := RecNo(), dbGoBottom(), my_QOut( o, {
"BOT", RecNo(), nOldRecNo } ) }
o:SkipBlock := { | nRecs | nOldRecNo := RecNo(), tmp := Skipped( nRecs
), my_QOut( o, { "SKP", RecNo(), nOldRecNo, nRecs, tmp } ), tmp }
o:AddColumn( TBColumnNew( "#", {|| my_QOut( NIL, { "BLK", RecNo() } ),
StrZero( RecNo(), 3 ) } ) )
#define Inkey(x)
CLS
TEST_CALL( o:leftVisible )
TEST_CALL( o:goTop() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:goTop() )
TEST_CALL( o:pageUp() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:goTop() )
TEST_CALL( o:pageDown() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:goBottom() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:goBottom() )
TEST_CALL( o:pageUp() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:goBottom() )
TEST_CALL( o:pageDown() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:leftVisible )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:rowPos )
TEST_CALL( o:rowPos )
TEST_CALL( dbGoTop() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:goTop() )
TEST_CALL( o:goBottom() )
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:up() )
TEST_CALL( o:up() )
TEST_CALL( o:down() )
// dbGoTop()
TEST_CALL( ForceStable( o ) )
TEST_CALL( o:PageUp() )
TEST_CALL( ForceStable( o ) )
o:goTop()
o:forceStable()
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:PageDown() )
TEST_CALL( o:PageDown() )
TEST_CALL( o:PageUp() )
TEST_CALL( ForceStable( o ) )
Inkey(0)
TEST_CALL( o:goTop() )
TEST_CALL( o:PageDown() )
TEST_CALL( ForceStable( o ) )
Inkey(0)
TEST_CALL( o:goTop() )
TEST_CALL( o:down() )
TEST_CALL( ForceStable( o ) )
Inkey(0)
TEST_CALL( o:goTop() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( ForceStable( o ) )
Inkey(0)
TEST_CALL( o:goBottom() )
TEST_CALL( ForceStable( o ) )
Inkey(0)
TEST_CALL( o:goBottom() )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
Inkey(0)
TEST_CALL( o:goBottom() )
TEST_CALL( o:pageDown() )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
Inkey(0)
TEST_CALL( o:goTop() )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
Inkey(0)
TEST_CALL( o:goTop() )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:down() )
TEST_CALL( o:stabilize )
Inkey(0)
TEST_CALL( o:goTop() )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:down() )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
TEST_CALL( o:stabilize )
Inkey(0)
/*
o:Stabilize()
o:Up()
o:Down()
o:PageUp()
o:PageDown()
o:GoTop()
o:GoBottom()
*/
RETURN NIL
STATIC FUNCTION Skipped( nRecs )
LOCAL nSkipped := 0
IF LastRec() != 0
IF nRecs == 0
dbSkip( 0 )
ELSEIF nRecs > 0 .AND. RecNo() != LastRec() + 1
DO WHILE nSkipped < nRecs
dbSkip()
IF Eof()
dbSkip( -1 )
EXIT
ENDIF
nSkipped++
ENDDO
ELSEIF nRecs < 0
DO WHILE nSkipped > nRecs
dbSkip( -1 )
IF Bof()
EXIT
ENDIF
nSkipped--
ENDDO
ENDIF
ENDIF
RETURN nSkipped
FUNCTION XToStrE( xValue )
LOCAL cType := ValType( xValue )
DO CASE
CASE cType == "C"
xValue := StrTran( xValue, Chr(0), '"+Chr(0)+"' )
xValue := StrTran( xValue, Chr(9), '"+Chr(9)+"' )
xValue := StrTran( xValue, Chr(10), '"+Chr(10)+"' )
xValue := StrTran( xValue, Chr(13), '"+Chr(13)+"' )
xValue := StrTran( xValue, Chr(26), '"+Chr(26)+"' )
RETURN xValue
CASE cType == "N" ; RETURN LTrim( Str( xValue ) )
CASE cType == "D" ; RETURN DToS( xValue )
CASE cType == "L" ; RETURN iif( xValue, ".T.", ".F." )
CASE cType == "O" ; RETURN xValue:className() + " Object"
CASE cType == "U" ; RETURN "NIL"
CASE cType == "B" ; RETURN '{||...} -> ' + XToStrE( Eval( xValue ) )
CASE cType == "A" ; RETURN '{ ' + ArrayToEList( xValue ) + ' }'
CASE cType == "M" ; RETURN 'M:' + xValue
ENDCASE
RETURN ""
FUNCTION ArrayToEList( a )
LOCAL tmp
LOCAL cString := ""
FOR tmp := 1 TO Len( a )
cString += XToStrE( a[ tmp ] )
IF tmp < Len( a )
cString += ", "
ENDIF
NEXT
RETURN cString
FUNCTION ForceStable( o )
DO WHILE !TEST_CALL( o:stabilize )
ENDDO
RETURN NIL
FUNCTION TEST_C_CALL( o, cBlock, bBlock )
LOCAL xRetVal
LOCAL cOldBlock := s_cCurrBlock
s_cCurrBlock := cBlock
LOGSTUFF( o, .T., "BEGIN" )
xRetVal := Eval( bBlock )
LOGSTUFF( o, .T., "END" )
s_cCurrBlock := cOldBlock
RETURN xRetVal
FUNCTION LOGSTUFF( o, l, cText )
STATIC s_nRow := 0
IF s_nRow == MaxRow()
Scroll( 0, 16, MaxRow(), MaxCol(), 1, 0 )
DispOutAt( MaxRow(), 0, Space( MaxCol() + 1 ) )
ELSE
s_nRow++
ENDIF
#define DispOut( x ) OutStd( x )
SetPos( s_nRow, 16 + iif( l, 0, 3 ) )
DispOut( ++s_nCount ) ; DispOut( " " )
DispOut( PadR( iif( l, s_cCurrBlock, "" ), 11 ) ) ; DispOut( " " )
DispOut( iif( o != NIL, o:rowPos, PadL( "", 10 ) ) ) ; DispOut( " " )
DispOut( cText ) ; DispOut( " " )
DispOut( Chr( 13 ) + Chr( 10 ) )
RETURN NIL
FUNCTION my_QOut( o, a )
LOGSTUFF( o, .F., ArrayToEList( a ) )
RETURN NIL
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour