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.