123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- {%skiptarget=$nothread }
- { %TIMEOUT=105 }
- {$mode objfpc}{$h+}
- uses
- {$ifdef UNIX}
- cthreads,
- {$endif}
- sysutils,
- classes;
- const
- fifolength = 1024;
- type
- tpair = class;
- tproducethread = class(tthread)
- running: boolean;
- pair: tpair;
- constructor create(apair: tpair);
- procedure execute; override;
- end;
- tconsumethread = class(tthread)
- running: boolean;
- pair: tpair;
- constructor create(apair: tpair);
- procedure execute; override;
- end;
- tpair = class(tobject)
- public
- readindex: integer;
- writeindex: integer;
- fifo: array[0..fifolength-1] of pointer;
- shared: pointer;
- freefifolock: trtlcriticalsection;
- produce_thread: tproducethread;
- consume_thread: tconsumethread;
- constructor create;
- destructor destroy; override;
- procedure resume;
- procedure waitfor;
- end;
- var
- done: boolean;
- constructor tproducethread.create(apair: tpair);
- begin
- pair := apair;
- inherited create(false);
- end;
- constructor tconsumethread.create(apair: tpair);
- begin
- pair := apair;
- inherited create(false);
- end;
- constructor tpair.create;
- begin
- filldword(fifo, sizeof(fifo) div sizeof(dword), 0);
- readindex := 0;
- writeindex := 0;
- initcriticalsection(freefifolock);
- produce_thread := tproducethread.create(self);
- consume_thread := tconsumethread.create(self);
- end;
- destructor tpair.destroy;
- begin
- produce_thread.free;
- consume_thread.free;
- donecriticalsection(freefifolock);
- end;
- procedure tpair.resume;
- begin
- produce_thread.resume;
- consume_thread.resume;
- end;
- procedure tpair.waitfor;
- begin
- produce_thread.waitfor;
- consume_thread.waitfor;
- end;
- type
- ttestarray = array[0..31] of pointer;
- procedure exercise_heap(var p: ttestarray; var i, j: integer);
- begin
- if p[i] = nil then
- p[i] := getmem(((j*11) mod 532)+8)
- else begin
- freemem(p[i]);
- p[i] := nil;
- end;
- inc(i);
- if i >= 32 then
- dec(i, 32);
- inc(j, 13);
- if j >= 256 then
- dec(j, 256);
- end;
- procedure freearray(p: ppointer; count: integer);
- var
- i: integer;
- begin
- for i := 0 to count-1 do
- begin
- freemem(p[i]);
- p[i] := nil;
- end;
- end;
- procedure producer(pair: tpair);
- var
- p: ttestarray;
- i, j, k: longint;
- begin
- done := false;
- filldword(p, sizeof(p) div sizeof(dword), 0);
- i := 0;
- j := 0;
- k := 0;
- while not done do
- begin
- if ((pair.writeindex+1) mod fifolength) <> pair.readindex then
- begin
- { counterpart for the writebarrier in the consumer: ensure that we see
- the write to pair.fifo[pair.readindex] now that we've seen the write
- to pair.readindex }
- readbarrier;
- freemem(pair.fifo[pair.writeindex]);
- pair.fifo[pair.writeindex] := getmem(((pair.writeindex*17) mod 520)+8);
- writebarrier;
- pair.writeindex := (pair.writeindex + 1) mod 1024;
- end else begin
- exercise_heap(p,i,j);
- inc(k);
- if k = 100 then
- begin
- k := 0;
- ThreadSwitch;
- end;
- end;
- end;
- freearray(p, sizeof(p) div sizeof(pointer));
- entercriticalsection(pair.freefifolock);
- sleep(200);
- freearray(pair.fifo, sizeof(pair.fifo) div sizeof(pointer));
- freemem(pair.shared);
- leavecriticalsection(pair.freefifolock);
- end;
- procedure consumer(pair: tpair);
- var
- p: ttestarray;
- i, j, k: longint;
- begin
- done := false;
- filldword(p, sizeof(p) div sizeof(dword), 0);
- i := 0;
- j := 0;
- k := 0;
- entercriticalsection(pair.freefifolock);
- while not done do
- begin
- if pair.readindex <> pair.writeindex then
- begin
- { counterpart for the writebarrier in the producer: ensure that we see
- the write to pair.fifo[pair.writeindex] now that we've seen the write
- to pair.writeindex }
- readbarrier;
- freemem(pair.fifo[pair.readindex]);
- pair.fifo[pair.readindex] := getmem(((pair.writeindex*17) mod 520)+8);
- writebarrier;
- pair.readindex := (pair.readindex + 1) mod fifolength;
- end else begin
- exercise_heap(p,i,j);
- inc(k);
- if k = 100 then
- begin
- k := 0;
- ThreadSwitch;
- end;
- end;
- end;
- pair.shared := getmem(12);
- leavecriticalsection(pair.freefifolock);
- freearray(p, sizeof(p) div sizeof(pointer));
- end;
- procedure tproducethread.execute;
- begin
- running:=true;
- producer(pair);
- end;
- procedure tconsumethread.execute;
- begin
- running:=true;
- consumer(pair);
- end;
- const
- numpairs = 2;
- var
- pairs: array[1..numpairs] of tpair;
- i, iter, num_iterations: integer;
- begin
- num_iterations := 20;
- if paramcount > 0 then
- num_iterations := strtointdef(paramstr(1), num_iterations);
- for iter := 1 to num_iterations do
- begin
- done := false;
- for i := low(pairs) to high(pairs) do
- pairs[i] := tpair.create;
- for i := low(pairs) to high(pairs) do
- pairs[i].resume;
- { wait till all threads are really resumed }
- for i := low(pairs) to high(pairs) do
- while not(pairs[i].produce_thread.running) or not(pairs[i].consume_thread.running) do
- sleep(100);
- done := true;
- for i := low(pairs) to high(pairs) do
- begin
- pairs[i].waitfor;
- pairs[i].free;
- end;
- end;
- end.
|