Search code examples
multithreadingdelphidelphi-2006synchronizationtlist

Delphi2006 - Is there TList with TMultiReadExclusiveWriteSynchronizer?


I have external application that is multithreaded and this app is using my custom dll to do some things from that threads.
In this dll I have 2 functions that read from and write some data to TList.
I need that list to be freely read by those threads but only one can write at a time, the rest must wait for their time to write.

My question:
- is there in BDS 2006 a TList component that have TMREWSync capability or
- maybe You know any free third-party component that I can use in my app or
- maybe You have some customized TList code that can do things like this mentioned above.

Edit: I need something like TThreadList.LockList but only for writing to that list.

Thanks for any help.


Solution

  • It's simple enough to put together a TMultiReadExclusiveWriteSynchronizer and TList in the same manner as TThreadList. If you already know how these classes work, then you'll be able to follow the code below.

    type
      TReadOnlyList = class
      private
        FList: TList;
        function GetCount: Integer;
        function GetItem(Index: Integer): Pointer;
      public
        constructor Create(List: TList);
        property Count: Integer read GetCount;
        property Items[Index: Integer]: Pointer read GetItem;
      end;
    
      TMREWList = class
      private
        FList: TList;
        FReadOnlyList: TReadOnlyList;
        FLock: TMultiReadExclusiveWriteSynchronizer;
      public
        constructor Create;
        destructor Destroy; override;
        function LockListWrite: TList;
        procedure UnlockListWrite;
        function LockListRead: TReadOnlyList;
        procedure UnlockListRead;
      end;
    
    { TReadOnlyList }
    
    constructor TReadOnlyList.Create(List: TList);
    begin
      inherited Create;
      FList := List;
    end;
    
    function TReadOnlyList.GetCount: Integer;
    begin
      Result := FList.Count;
    end;
    
    function TReadOnlyList.GetItem(Index: Integer): Pointer;
    begin
      Result := FList[Index];
    end;
    
    { TMREWList }
    
    constructor TMREWList.Create;
    begin
      inherited;
      FList := TList.Create;
      FReadOnlyList := TReadOnlyList.Create(FList);
      FLock := TMultiReadExclusiveWriteSynchronizer.Create;
    end;
    
    destructor TMREWList.Destroy;
    begin
      FLock.Free;
      FReadOnlyList.Free;
      FList.Free;
      inherited;
    end;
    
    function TMREWList.LockListWrite: TList;
    begin
      FLock.BeginWrite;
      Result := FList;
    end;
    
    procedure TMREWList.UnlockListWrite;
    begin
      FLock.EndWrite;
    end;
    
    function TMREWList.LockListRead: TReadOnlyList;
    begin
      FLock.BeginRead;
      Result := FReadOnlyList;
    end;
    
    procedure TMREWList.UnlockListRead;
    begin
      FLock.EndRead;
    end;
    

    This is the most basic implementation possible. If you wish you could add some more bells and whistles in the manner of TThreadList.