in Source/PLCrashAsyncLinkedList.hpp [338:396]
template <typename V> void async_list<V>::nasync_remove_node (node *deleted_node) {
/* Lock the list from other writers. */
PLCR_COMPAT_LOCK_LOCK(&_write_lock); {
/* Find the record. */
node *item = _head;
while (item != NULL) {
if (item == deleted_node)
break;
item = item->_next;
}
/* If not found, nothing to do */
if (item == NULL) {
PLCR_COMPAT_LOCK_UNLOCK(&_write_lock);
return;
}
/*
* Atomically make the item unreachable by readers.
*
* This serves as a synchronization point -- after the CAS, the item is no longer reachable via the list.
*/
if (item == _head) {
if (!_head.compare_exchange_strong(item, item->_next)) {
PLCF_DEBUG("Failed to remove image list head despite holding lock");
}
} else {
/* There MUST be a non-NULL prev pointer, as this is not HEAD. */
if (!item->_prev->_next.compare_exchange_strong(item, item->_next)) {
PLCF_DEBUG("Failed to remove image list item despite holding lock");
}
}
/* Now that the item is unreachable, update the prev/tail pointers. These are never accessed without a lock,
* and need not be updated atomically. */
if (item->_next != NULL) {
/* Item is not the tail (otherwise next would be NULL), so simply update the next item's prev pointer. */
((node *)item->_next)->_prev = item->_prev;
} else {
/* Item is the tail (next is NULL). Simply update the tail record. */
_tail = item->_prev;
}
/* If a reader is active, place the node on the free list. The item is unreachable here when readers
* aren't active, so if we have a 0 refcount, we can safely delete the item, and be sure that no
* reader holds a reference to it. */
if (_refcount > 0) {
item->_prev = NULL;
item->_next = _free;
if (_free != NULL)
_free->_prev = item;
_free = item;
} else {
delete item;
}
} PLCR_COMPAT_LOCK_UNLOCK(&_write_lock);
}