Hard Core Threading (TMREWS on Linux)
- From: warren.bare@xxxxxxxxx
- Date: 30 May 2005 08:29:22 -0700
On Linux Borland downgrades the TMultiReadExclusiveWriteSynchronizer to
a TSimpleRWSync which is basically just a TCriticalSection.
I don't know why it was hard to solve this problem. If you are a
thread guru, please help me understand.
I wrote a platform independant TMREWS (included below). The only
limitation is that you can not enter a write lock from within a read
lock.
Check it out. It seems to work, but I have not run it under a big
load, so if I have a problem ahead that I don't see, please let me
know.
Many Thanks,
Warren
unit ReadWriteSync;
interface
uses
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
{$IFDEF LINUX}
Types,
Libc,
{$ENDIF} SysUtils;
type
{
Limitations:
1) Do not call BeginWrite while you are holding a read lock.
2) The MaxReadTime on Create should only be used to debug bad
code using this unit.
}
TReadWriteSync = class
protected
FReaders: Integer;
FMaxReadTime: Cardinal;
FRevisionLevel: Integer;
FLock: TRTLCriticalSection;
public
Property Readers: Integer read FReaders;
Property RevisionLevel: Integer read FRevisionLevel;
Procedure BeginRead;
{
Must release read lock (EndRead) before BeginWrite. As a result
writers must assume the data has changed between locks.
}
Procedure BeginWrite;
Procedure EndRead;
Procedure EndWrite;
{
If you are having problems with deadly embrace, and you can't get
your code to correctly enter and leave matching locks, then as
a LAST RESORT, you can kludge your way around it with MaxReadTime.
MaxReadTime represents a number of milliseconds big enough that
no reader would ever ever ever hold a lock that long. This
represents the time AFTER the reader has a lock. It does not
include any time to acquire the lock.
For instance, if a reader can always get done with its work within
10 or 20 milliseconds, then maybe set this to 2000. The ONLY time
this will come into play is if the caller has failed to release a
read lock (typically because they had an unhandled exception), which
is just bad coding on the caller's part.
You should not rely on this. Passing in a value of 0 will mean it
waits for readers to finish no matter what. This is the best case
and will work fine if you have good code.
}
Constructor Create(MaxReadTime: Cardinal=0);
Destructor Destroy; override;
end;
implementation
Procedure TReadWriteSync.BeginRead;
begin
// Readers must aquire lock to start reading, but
// they don't keep the lock. This is just to be sure
// no one is writing.
EnterCriticalSection(FLock);
InterlockedIncrement(FReaders);
LeaveCriticalSection(FLock);
end;
Procedure TReadWriteSync.EndRead;
begin
// Readers leave easily. Thread safe Dec, but no lock.
// This means there is no way a reader can get stopped
// as they are leaving.
InterlockedDecrement(FReaders);
end;
Procedure TReadWriteSync.BeginWrite;
var
CurWait: Cardinal;
begin
// Don't try to write until you get a full lock
EnterCriticalSection(FLock);
CurWait:=0;
// Now wait for readers to finish up. Now that I have a lock
// we know that no new readers can start. All the existing
// readers should drop out quickly.
while FReaders > 0 do
begin
if (CurWait > FMaxReadTime) then
begin
// OUCH!!! This is not good. The caller has some messed
// up code because FReaders did not decrement to 0. We
// will fix it quietly. This is very dangerous.
FReaders := 0;
end
else
begin
Inc(CurWait,10);
sleep(10);
end;
end;
// I am about to write, so inc the revision
InterlockedIncrement(FRevisionLevel);
end;
Procedure TReadWriteSync.EndWrite;
begin
// when I stop writing, I release the big lock. This will
// let all the readers back in again.
LeaveCriticalSection(FLock);
end;
constructor TReadWriteSync.Create(MaxReadTime: Cardinal=0);
begin
inherited Create;
if MaxReadTime=0 then
FMaxReadTime := MaxInt
else
FMaxReadTime:= MaxReadTime;
InitializeCriticalSection(FLock);
end;
destructor TReadWriteSync.Destroy;
begin
inherited Destroy;
DeleteCriticalSection(FLock);
end;
end.
.
- Follow-Ups:
- Re: Hard Core Threading (TMREWS on Linux)
- From: Marco van de Voort
- Re: Hard Core Threading (TMREWS on Linux)
- Prev by Date: Re: MODI OCR "class not registered"
- Next by Date: Re: Interfaces...am i missing the point?
- Previous by thread: Interfaces...am i missing the point?
- Next by thread: Re: Hard Core Threading (TMREWS on Linux)
- Index(es):
Relevant Pages
|
|