in sdk/core/azure-core/src/main/java/com/azure/android/core/util/CancellationToken.java [129:197]
public void unregisterOnCancel(String id) {
if (this == CancellationToken.NONE) {
return;
}
OnCancelNode itr = this.onCancelNodes;
// Step_1: Locate the node and mark it as logically deleted.
//
while (itr != null) {
if (this.onCancelNodes == OnCancelNode.FROZEN) {
// The token is cancelled, no use in progressing.
return;
}
if (itr.id != null && itr.id.equals(id)) {
// Mark the node as logically deleted.
itr.markDeleted();
break;
}
itr = itr.next;
}
if (itr == null) {
// A node with id was not found.
return;
}
// Step_2: Sweep to unlink all logically deleted nodes.
//
boolean hadRace;
do {
// Outer 'do-while' to retry on any race during sweep.
hadRace = false;
OnCancelNode predecessor = null;
OnCancelNode current = this.onCancelNodes; // re-fetch the volatile head for each retry.
if (current == OnCancelNode.FROZEN) {
// The token is cancelled, no use in sweeping.
return;
}
OnCancelNode successor;
// Inner 'while' to sweep & unlink all logically deleted nodes.
while (current != null) {
successor = current.next;
if (current.isDeleted()) {
// Un-linking 'current' node.
if (predecessor == null) {
// The 'current' node has no 'predecessor' hence it's head, try CAS head with 'successor'.
if (!ON_CANCEL_NODES_UPDATER.compareAndSet(this, current, successor)) {
// Raced with
// 1. another thread calling registerOnCancelCallback.
// 2. OR the 'cancel()' call.
// need to retry.
hadRace = true;
break;
}
} else {
// The 'current' node has a 'predecessor'.
predecessor.next = successor;
if (predecessor.isDeleted()) {
// Raced with another thread that unlinked 'predecessor', need to retry.
hadRace = true;
break;
}
}
} else {
// We aren't un-linking 'current' node, update 'predecessor'.
predecessor = current;
}
current = successor;
}
} while (hadRace);
}