La liste des principaux intrinsics est :

La version simple :
– chaque thread incremente et décrémente librement. On commence à zéro et on augmente. On ne peut pas resdescendre en-desous de zéro.
Interlocked increment et Decrement renvoient la valeur après l’opération.

– En Acquistion:
on teste sans lock si le compteur est zéro.
Si oui, on demande le lock d’écriture du pointeur.
Si on obtient le lock, on refait l’incrémentation.
Si elle passe de zéro à 1, on alloue le pointeur, puis on libère le lock.
Sinon on lit juste le pointeur avant de libérer le lock, car celui qui a obtenu le lock avant nous l’a déjà alloué et écrit.
Si le compteur sans lock est supérieur à zéro, … argh c’est pas si simple …

Mauvais scénario :
Au départ, Compteur zéro, pointeur NULL
– t1 incrémente, obtient 1 il doit allouer
– t2 incrément, obtient 2, cherche à lire le pointeur.
– t2 constate que le pointeur est NULL, il doit attendre.
– t1 écrit la valeur du pointeur alloué
– t2 prend la valeur du pointeur
– t2 décrémente, obtient 1
– t1 décremente, obtient 0, il doit mettre le pointeur à NULL, mais argh, il est dé-schedulé avant !
– t3 incrémente, obtient 1, mais tiens le pointeur n’est pas NULL ?
– t4 incrémente, obtient 2, le pointeur n’est pas NULL, prend le pointeur et travaille avec
– t1 reprend enfin la main, met le pointeur à NULL, puis le libère alors que t4 est en train de travailler avec => FATAL ERROR

Recommençons avec -1 (free) et (0 in alloc/desalloc) :
Au départ, Compteur -1, pointeur NULL
– t1 lit, il voit -1
– t2 lit, il voit -1
– t1 fait un compareExchange qui écrit 0 si la valeur est toujours -1
– t1 a réussi son compareExchange, il doit allouer
– t2 fait le même compareExchange qui échoue, il doit attendre
– t2 lit, il voit zéro, il doit attendre
– t1 écrit le nouveau pointeur, et incrémente la valeur à 1
– t2 lit, voit que la valeur est supérieure à 0, il n’a plus besoin d’attendre
– t2 incrémente la valeur à 2 et prend le pointeur
– t2 décrémente, obtient 1
– t1 décremente, obtient 0, il doit mettre le pointeur à NULL, mais argh, il est dé-schedulé avant !
– t3 lit, il voit zéro, il doit attendre
– t1 remet le pointeur à NULL, puis décrémente à -1
– t3 lit, il voit -1
– t4 qui arrive en même temps va voir -1 ou bien voir 0, peut importe seul l’un des deux entre t3 et t4 prendra la tache d’allouer le pointeur et l’autre attendra sans souci.