unit SimpleSync;
{ Martin Harvey 27/5/2000 }
interface
uses Windows;
type
TSimpleSynchronizer = class(TObject)
private
FDataLock, FWriteLock: TRTLCriticalSection;
FActRead, FReadRead, FActWrite, FWriteWrite: integer;
FReaderSem, FWriterSem: THandle;
protected
public
constructor Create;
destructor Destroy; override;
procedure StartRead;
procedure StartWrite;
procedure EndRead;
procedure EndWrite;
published
end;
implementation
constructor TSimpleSynchronizer.Create;
begin
inherited Create;
InitializeCriticalSection(FDataLock);
InitializeCriticalSection(FWriteLock);
FReaderSem := CreateSemaphore(nil, 0, High(Integer), nil);
FWriterSem := CreateSemaphore(nil, 0, High(Integer), nil);
{ Initial values of 0 OK for all counts }
end;
destructor TSimpleSynchronizer.Destroy;
begin
DeleteCriticalSection(FDataLock);
DeleteCriticalSection(FWriteLock);
CloseHandle(FReaderSem);
CloseHandle(FWriterSem);
inherited Destroy;
end;
procedure TSimpleSynchronizer.StartRead;
begin
EnterCriticalSection(FDataLock);
Inc(FActRead);
if FActWrite = 0 then
begin
Inc(FReadRead);
ReleaseSemaphore(FReaderSem, 1, nil);
end;
LeaveCriticalSection(FDataLock);
WaitForSingleObject(FReaderSem, INFINITE);
end;
procedure TSimpleSynchronizer.StartWrite;
begin
EnterCriticalSection(FDataLock);
Inc(FActWrite);
if FReadRead = 0 then
begin
Inc(FWriteWrite);
ReleaseSemaphore(FWriterSem, 1, nil);
end;
LeaveCriticalSection(FDataLock);
WaitForSingleObject(FWriterSem, INFINITE);
EnterCriticalSection(FWriteLock);
end;
procedure TSimpleSynchronizer.EndRead;
begin
EnterCriticalSection(FDataLock);
Dec(FReadRead);
Dec(FActRead);
if FReadRead = 0 then
begin
while FWriteWrite < FActWrite do
begin
Inc(FWriteWrite);
ReleaseSemaphore(FWriterSem, 1, nil);
end;
end;
LeaveCriticalSection(FDataLock);
end;
procedure TSimpleSynchronizer.EndWrite;
begin
LeaveCriticalSection(FWriteLock);
EnterCriticalSection(FDataLock);
Dec(FWriteWrite);
Dec(FActWrite);
if FActWrite = 0 then
begin
while FReadRead < FActRead do
begin
Inc(FReadRead);
ReleaseSemaphore(FReaderSem, 1, nil);
end;
end;
LeaveCriticalSection(FDataLock);
end;
end.