he following is the implementation of the NonBlockingQueue::push member
function.
First, line 04, we get a pointer to an Element "el" via get() that reads and
increments theSwitch. Then, line 10, we attempt to gain ownership of el's
mutex. If successful, line 11, then we gain ownership of Node's mutex, line
13, and do the insertion, line 16. If gaining ownership at line 10 fails then
we proceed to the next Element on the line 19. The line 21 is added to insure
that any accidental call pattern that may lead to repeated failure would be
broken. It does exactly what it says: delays for a small random amount of
time. If everything fails, which should be extremely rare, an exception is
thrown from line 23.
01\template <class Data>
02\
void
NonBlockingQueue<Data>::push(
volatile
typename NonBlockingQueue<Data>::Node& node
)
volatile
03\
{
04\
volatile
Element* el=get();
05\
for(
int j=0; j<100; ++j )
06\
{
07\
int
L=circleLength();
08\
for(
int i=0; i<L; ++i )
09\
{
10\
ElementTryGuard
el_(el);
11\
if(
el_ )
12\
{
13\
NodeWriterGuard
node_(node);
14\
if(
node_->isInQueue() )
15\
return;
16\
Node::doInsert(el_,node_);
17\
return;
18\
}
19\
el=el->next();
20\
}
21\
SmallRandomDelay();
22\
}
23\
throw
UnableToPush();
24\
}
|