Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.pascal.misc > #734
| From | aminer <aminer@toto.net> |
|---|---|
| Newsgroups | comp.lang.pascal.misc |
| Subject | Here is my reasonning again |
| Date | 2014-04-24 20:28 -0700 |
| Organization | albasani.net |
| Message-ID | <ljca7u$3tm$3@news.albasani.net> (permalink) |
Here is my reasonning again, i think my reasonning is correct
so my proof is correct... please read again...
Hello,
Question:
Amine, how can we know that your algorithm of your
new concurrent FIFO queue works ? is it formally proved ?
Answer:
You can simply reason about the algorithm to prove that it is
correct , i will do it in front of you...
You can download the source code of the algorithm from here:
http://pages.videotron.com/aminer/
We begin by the pop() method, its source code look like this:
===
function TWQueue.push(tm : long):boolean;
var lastHead,newtemp:long;
i,j:integer;
begin
if getlength >= fsize
then
begin
result:=false;
exit;
end;
newTemp:=LockedIncLong(head);
lastHead:=newtemp-1;
repeat
asm pause end;
until fcount1^[lastHead and fMask].flag=0;
setObject(lastHead,tm);
fcount1^[lastHead and fMask].flag:=1;
if fwait then sema.signal;
result:=true;
end;
===
you have to know that "fsize" is fixed to the length of the queue
minus a "margin" that is equal to 1000 , that means that it's limited to
1000 threads in total that can run at the same time the push(), but you
can vary the margin to higher the number of threads that can
run the push() at the same time...
So if getlength equal fsize-1 that means that 1000 threads can cross
because "if getlength >= fsize" can be false at the same time, but
even if it is false at the same time , there a margin of 1000 threads,
so my reasonning is correct here.
Now we look at the rest of the code...
Every cell of the array based queue look like this:
type cell = record
obj:long;
flag:long;
{$IFDEF CPU32}
cache:typecache2;
{$ENDIF CPU32}
{$IFDEF CPU64}
cache:typecache3;
{$ENDIF CPU64}
end;
It's cache padded to a cache-line size and the array is aligned on
64 bytes so that to avoid false-sharing...
After that we increment the "head" like this with an atomic increment...
newTemp:=LockedIncLong(head);
lastHead:=newtemp-1;
and if fcount1^[lastHead and fMask].flag=0 that means there is no item
in the cell , we will write the item on the cell by doing this:
setObject(lastHead,tm);
and after that we set the flag of the cell to 1 so that the pop()
can read from it when it's set to 1 like this:
fcount1^[lastHead and fMask].flag:=1;
so as you have noticed i have reasonned and explained to you the push()
side, and i think my reasonning is correct here.
Now we will look at the pop() side, here is the code of the pop() side:
===
function TWQueue.pop(var obj:long):boolean;
var lastTail,newtemp,newtemp1,newtemp2 : long;
begin
if fwait then sema.wait;
repeat
newtemp1:=tail;
newtemp2:=newtemp1+1;
if newtemp2<=head then
else
begin
result:=false;
exit;
end;
if CAS(tail,newtemp1,newtemp2) then break;
sleep(0);
until false;
lastTail:=newtemp1;
repeat
asm pause end;
until fcount1^[lastTail and fMask].flag=1;
obj:=getObject(lastTail);
fcount1^[lastTail and fMask].flag:=0;
result:=true;
end;
==
The very first thing to know on the pop() side is that we must increment
the "tail" everytime but how can we increment the tail without going
over the "head", this is why in my invention i have used a lockfree
mechanism like this
==
repeat
newtemp1:=tail;
newtemp2:=newtemp1+1;
if newtemp2<=head then
else
begin
result:=false;
exit;
end;
if CAS(tail,newtemp1,newtemp2) then break;
sleep(0);
until false;
==
It's like in lockfree algorithms , i have to copy and memories
the "tail" into the newtemp1 variable and after that increment newtemp1
, so if newtemp1+1 is less or equal to "head" that means we are correct
and we have not go over the head , after that with a lockfree mechanism
we will test with a CAS that tail is still equal to newtemp1 to be able
to increment the "tail" , so my reasonnning is correct here.
After that we have to wait to see if there is an item in the cell by
doing this:
repeat
asm pause end;
until fcount1^[lastTail and fMask].flag=1;
If there is an item on the cell we will get it
and set the flag of the cell to 0 to say to
the push() threads that they can push() to this cell by doing this:
obj:=getObject(lastTail);
fcount1^[lastTail and fMask].flag:=0;
So as you have noticed this is my new algorithm
and i have presented to you my reasonning to prove
to you that my algorithm is correct, and i think
my algorithm is correct.
Thank you,
Amine Moulay Ramdane.
Back to comp.lang.pascal.misc | Previous | Next | Find similar
Here is my reasonning again aminer <aminer@toto.net> - 2014-04-24 20:28 -0700
csiph-web