> I don't think it's that complicated. After the copy has completed,
> the old table doesn't contain any references anymore, and can be
> freed without actually traversing it.
It's not enough to verify that the table isn't useful anymore; one
must ascertain that no other thread is still looking inside it. For
that a (concurrent) ref counter is required, and something like this
is still not safe when releasing it:
if (decrement_counter (cnt) == 0) { // Race from here
void *p = old_array_ptr;
old_array_ptr = NULL; // to here.
free (p);
}
To sort that out I think it's best to take the same approach as Cliff
Click and reason about it as a state machine with states made up of
{old_array_ptr, cnt}:
{NULL, 0} {NULL, >= 1} {*, 0} {*, >= 1}
We did it on a whiteboard today - a good excercise.
And of course, cnt (the index/"handle" of the concurrent counter)
cannot be stored inside the old hash table block - it has to be stored
alongside the pointer to it.
So it's solvable, but still requires some thought.