Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-09

Random thread lockup. QueueAsyncCall??

2 messages · 1 person ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Xiangrong Fang

Hi There,

I am writing my "prime finder" app to understand how thread synchronization works. I tried two methods (critical section and rtlevent), both have problem. For example the rtlevent version will run for a while then randomly stops. However, after the thread stops working it seems that the GUI is still responsive.

Here is three core functions from then rtlevent version:

procedure TPrimeFinder.Execute;
begin
  while not Terminated do begin
    RTLeventWaitFor(Barrier);
    if not IsPrime then Number := 0;
    Application.QueueAsyncCall(@AddPrime, PtrInt(Self));
    RTLeventResetEvent(Barrier);
  end;
end;
procedure TPrimeFinder.AddPrime(data: PtrInt);
var
  tr: TPrimeFinder;
begin
  tr := TPrimeFinder(data);
  with fmMain do begin
    if tr.Number > 0 then begin
      cnt += 1;
      if tr.Number > max then max := tr.Number;
    end;
    tr.Number := num;
    RTLeventSetEvent(tr.Barrier);
    Inc(num);
    leCount.Text := IntToStr(cnt);
    leMax.Text := IntToStr(max);
  end;
end;
procedure TfmMain.Button1Click(Sender: TObject);
var
  i, c: Integer;
begin
  num := 2;
  c := StrToIntDef(edThreads.Text, 1);
  if c < 1 then c := 1;
  SetLength(wk, c);
  for i := 0 to c - 1 do begin
    wk[i] := TPrimeFinder.Create(False);
    wk[i].FreeOnTerminate := True;
    wk[i].Barrier := RTLEventCreate;
    wk[i].Number := num;
    Inc(num);
    RTLeventSetEvent(wk[i].Barrier);
  end;
end;

I suspect that it is blocked on the RTLeventWaitFor, because if I use this:

    RTLeventWaitFor(Barrier, 1000);

It will periodically pause for 1 second, then continue.

Is this a problem in Application.QueueAsyncCall, or I made some mistakes?

Thanks!
Xiangrong

Reply by email

Xiangrong Fang
to Xiangrong Fang

2014-09-18 23:10 GMT+08:00 Xiangrong Fang :

Show quoted text 7 lines
I suspect that it is blocked on the RTLeventWaitFor, because if I use this: RTLeventWaitFor(Barrier, 1000); It will periodically pause for 1 second, then continue.

I found the problem myself. Instead of writing:

while not Terminated do begin
  RTLeventWaitFor(Barrier);
  if not IsPrime then Number := 0;
  Application.QueueAsyncCall(@AddPrime, PtrInt(Self));
  RTLeventResetEvent(Barrier);
end;

I should write:

while not Terminated do begin
  RTLeventWaitFor(Barrier);
  RTLeventResetEvent(Barrier);
  if not IsPrime then Number := 0;
  Application.QueueAsyncCall(@AddPrime, PtrInt(Self));
end;

Because when doing the AsyncCall, the main thread may have called RTLeventSetEvent BEFORE the RTLeventResetEvent() is called.

Xiangrong

Reply by email