__synchronisation_val_comparez_et_swap vs __synchronisation_bool_comparez_et_swap

J'ai été à la réflexion sur les valeurs de retour de ces deux fonctions. L' __synchronisation_bool_comparez_et_swap fonction de la valeur de retour semble avoir des avantages évidents, c'est à dire que je peux l'utiliser pour savoir si le swap opération a eu lieu. Cependant je ne peux pas voir d'un bon usage de __synchronisation_val_comparez_et_swaps valeur de retour.

Tout d'abord, permet d'avoir une signature de fonction de référence (à partir de GCC docs moins le var args):

type __sync_val_compare_and_swap (type *ptr, type oldval type newval);

Le problème que je vois est que la valeur de retour __synchronisation_val_comparez_et_swap est l'ancienne valeur de l' *ptr. Pour être précis, c'est la valeur qui a été vu par la mise en œuvre de cette fonction une fois les barrières de la mémoire avait été mis en place. Je mentionner explicitement pour répondre au fait que, entre l'appel __synchronisation_val_comparez_et_de swap et de l'exécution des instructions pour appliquer la barrière de la mémoire de la valeur de *ptr pourrait facilement changer.

Maintenant, lorsque la fonction renvoie ce que je peux faire avec cette valeur de retour? Il n'y a pas de point d'essayer de le comparer à *ptr, car *ptr peut maintenant être changé sur d'autres threads. De même, la comparaison de newval et *ptr n'a pas vraiment m'aider non plus (sauf si je lock *ptr qui a probablement sape mon utilisation de atomics en premier lieu).

Donc tout ce qui est vraiment me reste à faire est de demander si la valeur de retour == oldval, qui est effectivement (voir ci-dessous pour une mise en garde) en se demandant si le swap opération a eu lieu. Si je pouvais avoir juste utilisé __synchronisation_bool_comparez_et_swap.

La mise en garde que je viens de mentionner, c'est que la seule différence que je peux voir ici, est que cela ne me dites pas si le swap est survenue ou non, il m'a juste dit qu'à un certain moment avant de la barrière de la mémoire a été publié *ptr avait la même valeur que newval. Je suis en train d'étudier la possibilité que oldval == newval (bien que j'avais du mal a voir un moyen de mise en œuvre de la fonction de manière efficace afin qu'il puisse vérifier ces valeurs et pas de swap si elles étaient les mêmes, donc c'est probablement un point discutable). Cependant je ne peux pas voir une situation où le savoir cette différence serait de faire une différence pour moi sur le site d'appel. En fait, je ne peux pas imaginer une situation où je mettrais oldval et newval être égaux.

Ma question est donc:

Est-il un cas d'utilisation dans lesquels l'aide d' __synchronisation_val_comparez_et_swap et __ _ _ synchronisation_bool_comparez_et_swap ne serait pas d'équivalent, c'est à dire il y a une situation où l'on fournit plus d'informations que les autres?

De CÔTÉ

La raison pour laquelle je pensais c'était que j'ai trouvé une mise en œuvre de l' __synchronisation_val_comparez_et_swap en termes de sync_bool_compare_and_swap qui a une course:

inline int32_t __sync_val_compare_and_swap(volatile int32_t* ptr, int32_t oldval, int32_t newval)
{
    int32_t ret = *ptr;
    (void)__sync_bool_compare_and_swap(ptr, oldval, newval);
    return ret;
}

La course sur le stockage de l' *ptr en ret, *ptr pourrait changer avant d' __synchronisation_bool_comparez_et_swap est appelé. Cela m'a fait réaliser que je ne semble pas être un moyen sûr (sans obstacles ou des serrures) de la mise en œuvre __synchronisation_val_comparez_et_swap en termes de sync_bool_compare_and_swap. Cela m'a fait penser que l'ancien doit fournir plus de "l'information" que la seconde, mais que par ma question je ne vois pas qu'il fait vraiment.

Utilisation: le retour de valeur actuelle peut être utilisé pour une nouvelle tentative. Je sais qu'il y atomique incréments mais à des fins d'illustration, supposons que vous souhaitez mettre en œuvre. Vous pouvez simplement appeler la val_compare_and_swap avec oldvalue comme la pré-incrémentation et newvalue que pos-incrément. Si elle réussit, vous avez terminé. Si pas, vous pouvez recommencer en incrémentant la valeur renvoyée et l'appel de val_compare_and_swap de nouveau. Avec le bool version vous aurez besoin de faire une lecture supplémentaire de la valeur actuelle pour une nouvelle tentative.
Vous avez raison que le code dans votre "côté" est buggy/a un sérieux condition de course. Une nouvelle tentative de la boucle est nécessaire pour le rendre correct. Voir ma réponse.

OriginalL'auteur Andrew Parker | 2015-04-28