Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here is a sample that adds values in list1 and list2 from your three threads.</p> <p>Each time a value is put into a list, an <code>Event</code> is triggered and the thread handling this event pulls out the last value in the list and clears the event flag.</p> <p>No new value can be put into a list until the event flag is cleared.</p> <p>The middle thread makes an intermediate storage of a new value, not to stall the first thread.</p> <p>All events are waitable and thus keeps the cpu at ease.</p> <p>The lists are thread-safe.</p> <pre><code>program Project62; {$APPTYPE CONSOLE} uses System.SysUtils, System.Classes, System.SyncObjs, System.Generics.Collections; Type TMyThread1 = Class(TThread) private fMySyncAddList : TSimpleEvent; fMyList : TThreadList&lt;Integer&gt;; fAddVal : Integer; public Constructor Create(ASyncAddList: TSimpleEvent; AList: TThreadList&lt;Integer&gt;); procedure Execute; override; End; TMyThread2 = Class(TThread) private fMySyncAddList1,fMySyncAddList2 : TSimpleEvent; fMyList1,fMyList2 : TThreadList&lt;Integer&gt;; fAddVal : Integer; public Constructor Create(ASyncAddList1,ASyncAddList2: TSimpleEvent; AList1,AList2 : TThreadList&lt;Integer&gt;); procedure Execute; override; End; TMyThread3 = Class(TThread) private fMySyncAddList2 : TSimpleEvent; fMyList2 : TThreadList&lt;Integer&gt;; fAddVal : Integer; public Constructor Create(ASyncAddList2: TSimpleEvent; AList2 : TThreadList&lt;Integer&gt;); procedure Execute; override; End; { TMyThread1 } constructor TMyThread1.Create( ASyncAddList : TSimpleEvent; AList: TThreadList&lt;Integer&gt;); begin Inherited Create(false); fMySyncAddList := AsyncAddList; fMyList := AList; end; procedure TMyThread1.Execute; var stateAcknowledged : boolean; begin stateAcknowledged := true; while (not Terminated) do begin if stateAcknowledged then begin // Do some work and adda a value to list1 fAddVal := Random(100); fMyList.Add(fAddVal); fMySyncAddList.SetEvent; // Signal a new addition stateAcknowledged := false; //ShowVal; Sleep(1000); end else begin stateAcknowledged := (fMySyncAddList.WaitFor(100) &lt;&gt; wrSignaled); end; end; end; { TMyThread2 } constructor TMyThread2.Create(ASyncAddList1, ASyncAddList2: TSimpleEvent; AList1, AList2: TThreadList&lt;Integer&gt;); begin Inherited Create(false); fMySyncAddList1 := AsyncAddList1; fMySyncAddList2 := AsyncAddList2; fMyList1 := AList1; fMyList2 := AList2; end; procedure TMyThread2.Execute; var wr : TWaitResult; list : TList&lt;Integer&gt;; pulled : Boolean; begin pulled := false; while (not Terminated) do begin if pulled then // Add a value to list2 begin wr := fMySyncAddList2.WaitFor(0); if (wr &lt;&gt; wrSignaled) then begin fMyList2.Add(fAddVal); fMySyncAddList2.SetEvent; // Signal a new addition pulled := false; end else Sleep(100); end else begin // Wait for a new value in list1 wr := fMySyncAddList1.WaitFor(INFINITE); if Terminated then Exit; if (wr = wrSignaled) then begin // Pull out the value list := fMyList1.LockList; try fAddVal := list.Last; finally fMyList1.UnlockList; end; // All clear pulled := true; fMySyncAddList1.ResetEvent; //ShowVal; end; end; end; end; { TMyThread3 } constructor TMyThread3.Create(ASyncAddList2: TSimpleEvent; AList2: TThreadList&lt;Integer&gt;); begin Inherited Create(false); fMySyncAddList2 := AsyncAddList2; fMyList2 := AList2; end; procedure TMyThread3.Execute; var wr : TWaitResult; list : TList&lt;Integer&gt;; begin while not Terminated do begin wr := fMySyncAddList2.WaitFor(INFINITE); if Terminated then Exit; if (wr = wrSignaled) then // Wait for signal begin // Pull out the value list := fMyList2.LockList; try fAddVal := list.Last; //ShowVal; finally fMyList2.UnlockList; end; // Clear event fMySyncAddList2.ResetEvent; end; end; end; var list1,list2 : TThreadList&lt;Integer&gt;; syncList1,syncList2 : TSimpleEvent; thread1 : TMyThread1; thread2 : TMyThread2; thread3 : TMyThread3; begin list1 := TThreadList&lt;Integer&gt;.Create; list2 := TThreadList&lt;Integer&gt;.Create; syncList1 := TSimpleEvent.Create(Nil,True,False,'',false); syncList2 := TSimpleEvent.Create(Nil,True,False,'',false); thread3 := TMyThread3.Create(syncList2,list2); thread2 := TMyThread2.Create(syncList1,syncList2,list1,list2); thread1 := TMyThread1.Create(syncList1,list1); Try WriteLn('Press [Enter] key to stop.'); ReadLn; Finally thread3.Terminate; syncList2.SetEvent; // Wake up call thread3.Free; thread2.Terminate; syncList1.SetEvent; // Wake up call thread2.Free; thread1.Free; syncList1.Free; syncList2.Free; list1.Free; list2.Free; End; end. </code></pre> <hr> <p>Added an example where two <code>TThreadedQueue</code>'s transfer the information between the threads. The threads keeps internal lists of the integers instead. The code is much simpler as @DavidHeffernan points out. </p> <pre><code>program Project63; {$APPTYPE CONSOLE} uses   System.SysUtils,   System.Classes,   System.SyncObjs,   System.Generics.Collections; Type   TMyThread1 = Class(TThread)     private       fMyList : TList&lt;Integer&gt;;       fMyQueue : TThreadedQueue&lt;Integer&gt;;       fAddVal : Integer;     public       Constructor Create(AQueue : TThreadedQueue&lt;Integer&gt;);       procedure Execute; override;   End;   TMyThread2 = Class(TThread)     private       fMyList1,fMyList2 : TList&lt;Integer&gt;;       fMyQueue1,fMyQueue2 : TThreadedQueue&lt;Integer&gt;;       fAddVal : Integer;     public       Constructor Create(AQueue1,AQueue2: TThreadedQueue&lt;Integer&gt;);       procedure Execute; override;   End;   TMyThread3 = Class(TThread)     private       fMyList : TList&lt;Integer&gt;;       fMyQueue : TThreadedQueue&lt;Integer&gt;;       fAddVal : Integer;     public       Constructor Create(AQueue : TThreadedQueue&lt;Integer&gt;);       procedure Execute; override;   End; constructor TMyThread1.Create( AQueue : TThreadedQueue&lt;Integer&gt;); begin   Inherited Create(false);   fMyQueue:= AQueue;   fMyList := TList&lt;Integer&gt;.Create; end; procedure TMyThread1.Execute; begin   while (not Terminated) do   begin     Sleep(1000); // Simulate some work     fAddVal := Random(100);     fMyList.Add(fAddVal);     fMyQueue.PushItem(fAddVal); // Signal a new addition   end;   fMyList.Free; end; constructor TMyThread2.Create(AQueue1,AQueue2: TThreadedQueue&lt;Integer&gt;); begin   Inherited Create(false);   fMyQueue1 := AQueue1;   fMyQueue2 := AQueue2;   fMyList1 := TList&lt;Integer&gt;.Create;   fMyList2 := TList&lt;Integer&gt;.Create; end; procedure TMyThread2.Execute; var   queueSize : Integer; begin   while (not Terminated) do   begin     if (fMyQueue1.PopItem(queueSize,fAddVal) = wrSignaled) and (not Terminated) then     begin       fMyList1.Add(fAddVal);       // Do some work and send a new value to next thread       fMyQueue2.PushItem(fAddVal); fMyList2.Add(fAddVal);           end;   end;   fMyList1.Free;   fMyList2.Free; end; constructor TMyThread3.Create(AQueue : TThreadedQueue&lt;Integer&gt;); begin   Inherited Create(false);   fMyQueue := AQueue;   fMyList := TList&lt;Integer&gt;.Create; end; procedure TMyThread3.Execute; var   queueSize : Integer; begin   while not Terminated do   begin     if (fMyQueue.PopItem(queueSize,fAddVal) = wrSignaled) and (not Terminated) then     begin       fMyList.Add(fAddVal);       // Do some work on list           end;   end; fMyList.Free; end; var   queue1,queue2 : TThreadedQueue&lt;Integer&gt;;   thread1 : TMyThread1;   thread2 : TMyThread2;   thread3 : TMyThread3; begin   queue1 := TThreadedQueue&lt;Integer&gt;.Create;   queue2 := TThreadedQueue&lt;Integer&gt;.Create;   thread3 := TMyThread3.Create(queue2);   thread2 := TMyThread2.Create(queue1,queue2);   thread1 := TMyThread1.Create(queue1);   Try     WriteLn('Press [Enter] key to stop.');     ReadLn;   Finally     thread3.Terminate;     queue2.PushItem(0); // Wake up call     thread3.Free;     thread2.Terminate;     queue1.PushItem(0); // Wake up call     thread2.Free;     thread1.Free;     queue1.Free;     queue2.Free;   End; end. </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload