unit EventSync; { Martin Harvey 5/6/2000 } interface uses Windows; type TEventSynchronizer = class(TObject) private FDataLock, FWriteLock: TRTLCriticalSection; FReaders, FWriters: integer; FNoReaders, FNoWriters: THandle; protected public constructor Create; destructor Destroy; override; procedure StartRead; procedure StartWrite; procedure EndRead; procedure EndWrite; published end; implementation constructor TEventSynchronizer.Create; begin inherited Create; InitializeCriticalSection(FDataLock); InitializeCriticalSection(FWriteLock); FNoReaders := CreateEvent(nil, true, true, nil); FNoWriters := CreateEvent(nil, true, true, nil); end; destructor TEventSynchronizer.Destroy; begin DeleteCriticalSection(FDataLock); DeleteCriticalSection(FWriteLock); CloseHandle(FNoReaders); CloseHandle(FNoWriters); inherited Destroy; end; procedure TEventSynchronizer.StartRead; var Block: boolean; begin EnterCriticalSection(FDatalock); if FReaders = 0 then ResetEvent(FNoReaders); Inc(FReaders); Block := FWriters > 0; LeaveCriticalSection(FDataLock); if Block then WaitForSingleObject(FNoWriters, INFINITE); end; procedure TEventSynchronizer.StartWrite; var Block: boolean; begin EnterCriticalSection(FDataLock); if FWriters = 0 then ResetEvent(FNoWriters); Inc(FWriters); Block := FReaders > 0; LeaveCriticalSection(FDataLock); if Block then WaitForSingleObject(FNoReaders, INFINITE); EnterCriticalSection(FWriteLock); end; procedure TEventSynchronizer.EndRead; begin EnterCriticalSection(FDataLock); Dec(FReaders); if FReaders = 0 then SetEvent(FNoReaders); LeaveCriticalSection(FDataLock); end; procedure TEventSynchronizer.EndWrite; begin LeaveCriticalSection(FWriteLock); EnterCriticalSection(FDataLock); Dec(FWriters); if FWriters = 0 then SetEvent(FNoWriters); LeaveCriticalSection(FDataLock); end; end.