[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


Reply via email to