title: Delphi static array thread safety only with critical section
body: <p>I have a Win32 Thread (no TThread) that runs alle the time and iterates over a static array. The mainthread can modify fields of the array. What is the best way to make this thread-safe <strong>without components like TThreadList</strong> (for a no-vcl application), only with Windows Critical Sections (TRTLCriticalSection)?</p>
  
  <p>Code:</p>
  
  <pre><code>type
    T = record
      Idx: Integer;
      Str: string;
      Num: Real;
      Enabled: Boolean;
    end;
  
  var
    A: Array[0..9] of T;
    Cnt: Integer;
    CS: TRTLCriticalSection;
  
  procedure thread;
  var
    I: Integer;
  begin
    while True do
    begin
      for I := Low(A) to High(A) do
      begin
        if A[I].Enabled then
        begin
          //modify some fields from A[I]
  
          Inc(A[I].Idx);
          if A[I].Idx &gt;= 10 then
          begin
            A[I].Enabled := False;
            InterlockedDecrement(Cnt);
          end;
        end;
      end;
      if Cnt = 0 then Sleep(1);
    end;
  end;
  
  procedure Add(...); //called only from mainthread
  
    function GetFreeField: Integer;
    begin
      for Result := Low(A) to High(A) do
        if not A[Result].Enabled then Exit;
      Result := -1;
    end;
  
  var
    I: Integer;
  begin
    I := GetFreeField;
    if I = -1 then Exit;
  
    //set fields A[I]
  
    A[I].Enabled := True;
    InterlockedIncrement(Cnt);
  end;
  </code></pre>
  
  <p>At the beginning the array is initialized with enabled = false and cnt = 0.</p>
  
  <p>Is the following modification sufficient?</p>
  
  <pre><code>procedure thread;
  var
    I: Integer;
  begin
    while True do
    begin
      for I := Low(A) to High(A) do
      begin
        EnterCriticalSection(CS);
        if A[I].Enabled then
        begin
          LeaveCriticalSection(CS);
          //modify some fields from A[I]
  
          Inc(A[I].Idx);
          if A[I].Idx &gt;= 10 then
          begin
            EnterCriticalSection(CS);
            A[I].Enabled := False;
            LeaveCriticalSection(CS);
  
            InterlockedDecrement(Cnt);
          end;
        end
        else
          LeaveCriticalSection(CS);
      end;
      if Cnt = 0 then Sleep(1);
    end;
  end;
  
  procedure Add(...); //called only from mainthread
  var
    I: Integer;
  begin
    I := GetFreeField;
    if I = -1 then Exit;
  
    //set fields A[I]
  
    EnterCriticalSection(CS);
    A[I].Enabled := True;
    LeaveCriticalSection(CS);
  
    InterlockedIncrement(Cnt);
  end;
  </code></pre>