[EMAIL PROTECTED] wrote:
> In the function below, I am using the Windows LockFile API.
>
> Caclulating which byte to lock comes from other logic, and the numbers can
> be large. I am getting a "range check error" on assignment.
LockFile takes four DWord parameters, but that's to accept the lower and
upper portions of a 64-bit integer. Delphi supports 64-bit integers, so
you might find it easier to do your work with Int64 and then split them in
half just to call the API function.
> Yet, as I understand it, a DWORD is:
>
> Longword 0..4294967295 unsigned 32-bit
>
> The value which throws the exception is 429,496,5455
> This is less than the documented max of 429,496,7295
Commas go on every third digit counting from the right, not the left, please.
> Any ideas on how to debug greatly appreciated, thank you.
>
>
> ==============================================================
> const
> {
> Row/Slot numbers are 0-origin
> Station/Task numbers are 1-origin
> A resource name determines a row/slot.
> 1st byte in region is "held exclusive"
> Remainder of region has 1 byte for every Station/Task.
> }
> EZMAXROW = 19; // EZSEMTAB data area
> EZPAGESIZE = 512; // EZSEMTAB data block
> EZBASE = EZMAXROW * EZPAGESIZE;
> EZRSCSIZE = 10;
> EZMAXTASK = 16;
> EZMAXSTATION= 512;
> EZMAXSLOT = 51;
> EZSLOTSIZE = 1+(EZMAXTASK * EZMAXSTATION); // Exclusive + one for
> everybody
> EZROWSIZE = (EZMAXSLOT * EZSLOTSIZE);
>
> ...........
>
> function TIMSPlusTask.Exclusive(rsc:string; const
> Table:TDataSet=nil):Boolean;
> var
> lower,upper:DWORD;
> begin
> ...
> Result:=False;
> while not Result do
> begin
> EZSEMTAB.Mutex := TRUE;
> // An exclusive lock requires a shared lock
> if not FLockList.Shared[iRow,iSlot] then
> begin
> if not EZSEMTAB.isLocked(iRegion,1) then
> EZSEMTAB.Lock(iByte) // Got shared access
> else
> begin
> // Can't get shared
> EZSEMTAB.Mutex := False;
> if RetryDialog then continue else break;
> end;
> end;
> { Are we now the only ones holding this resource?
> We should be able to lock either sides of this slot:
> everything outside our own task byte.
> iRegion < iByte <= (iRegion+EZSLOTSIZE-1)
> If yes, we may lock the iRegion EXCLUSIVE byte now.
> }
>
> lower := iByte - iRegion;
> upper := iRegion + (EZSLOTSIZE-1) - iByte; ******* RANGE CHECK ERROR
> HERE *******
Remember that these are evaluated from left to right. If the addition
exceeds High(DWord), then it doesn't matter whether subtracting iByte
would bring it back down below the limit -- the computation never gets
that far.
You say iRegion is 4,294,965,455. To that, you add EZSlotSize-1, which is
8,192. The sum is 4,294,973,647, which exceeds the limit of 4,294,967,296.
You asked for ideas on debugging. First idea: Split compound expressions
into simple expressions to narrow down where the error really is.
You didn't happen to get a warning at that line, did you? You're adding
something of type DWord with something of type Integer. I don't remember
whether that's performed as signed 32, unsigned 32, or signed 64.
> if (EZSEMTAB.isLocked(iRegion,lower)) or
> (EZSEMTAB.isLocked(iByte+1,upper)) then
> begin
> EZSEMTAB.Mutex:=False;
> EZSEMTAB.UnLock(iByte);
> if RetryDialog then continue else break;
> end else
> begin
> // Gotcha exclusive
> EZSEMTAB.Lock(iRegion);
> Result:=True;
> break;
> end;
It's a little peculiar for the last statement of a loop to be Break when
the loop-termination condition was just met on the previous line. Likewise
for the final statement of a loop to be Continue.
> end;
> EZSEMTAB.Mutex:=False;
>
> if Result then
> begin
> FLockList.Exclusive[iRow,iSlot]:=True;
> FLockList.Shared[iRow,iSlot]:=True;
> end else
> begin
> // We lost our shared hold when we put up the retry dialog form
> FLockList.Shared[iRow,iSlot]:=False;
> end;
>
> end;
--
Rob