2013-09-27 7 views
0

Je souhaite implémenter un verrou simple multi-lecteurs/moniteurs en utilisant une valeur volatile.ReaderWriter Mise en œuvre sans verrouillage

Bien que _InterlockedXXX fournisse une barrière de clôture complète et, si j'ai raison, aussi un mot-clé "volatile", je veux connaître les défauts et les améliorations possibles. Je n'ai aucune expérience avec la sémantique Acquérir/Libérer.

Mon code:

BOOL TryAcquireShared(LONG volatile *lpnValue) 
{ 
    LONG initVal; 

    do 
    { 
    initVal = *lpnValue; 
    if (initVal == 0x80000000L) 
     return FALSE; //a writer is active 
    } 
    while (_InterlockedCompareExchange(lpnValue, initVal+1, initVal) != initVal); 
    return TRUE; 
} 

VOID ReleaseShared(LONG volatile *lpnValue) 
{ 
    LONG initVal, newVal; 

    do 
    { 
    initVal = *lpnValue; 
    newVal = (initVal & 0x80000000L) | ((initVal & 0x7FFFFFFFL) - 1); 
    } 
    while (_InterlockedCompareExchange(lpnValue, newVal, initVal) != initVal); 
    return; 
} 

BOOL TryAcquireExclusive(LONG volatile *lpnValue) 
{ 
    LONG i, initVal, newVal; 

    do 
    { 
    initVal = *lpnValue; 
    if ((initVal & 0x80000000L) != 0) 
     return FALSE; //another writer is active or waiting 
    } 
    while (_InterlockedCompareExchange(lpnValue, initVal | 0x80000000L, initVal) != initVal); 
    //wait until no readers 
    while ((*lpnValue & 0x7FFFFFFFL) != 0) 
    ::Sleep(1); 
    return TRUE; 
} 

VOID ReleaseExclusive(LONG volatile *lpnValue) 
{ 
    _InterlockedExchange(lpnValue, 0); 
    return; 
} 

De plus, si vous connaissez une bibliothèque qui peut gérer cela, s'il vous plaît me dire.

Répondre

0
  • TryAcquireShared doit vérifier si * lpnValue est 0x7FFFFFFFL avant incrémenter.
  • ReleaseShared devrait affirmer que * lpnValue n'a pas le bit 0x80000000L au lieu d'essayer de le conserver. Un verrou exclusif ne doit pas exister si vous libérez un verrou partagé.
  • TryAcquireExclusive doit uniquement vérifier si * lpnValue est égal à zéro avant de définir le bit 0x80000000L.
  • Les deux acquis et l'exclusivité d'aquire doivent avoir un appel Sleep (1) chaque fois qu'une certaine quantité de spins.
  • Je ne comprends pas la partie suivante dans TryAcquireExclusive. Pourquoi attendriez-vous des lecteurs si vous avez juste un verrou exclusif?

    while ((* lpnValue & 0x7FFFFFFFL)! = 0) :: Sommeil (1);

+0

merci pour les commentaires. Le concept est le suivant: Lorsqu'un thread demande une exclusivité, le bit haut est activé afin que les autres threads demandant un type d'accès quelconque attendent. Aussi le fil demandant l'excl. lock attendra que les autres threads détenant déjà le verrou partagé finissent leur travail. À propos de '0x7FFFFFFFL' vérifier premier point, je n'ai pas fait la vérification parce que je suppose qu'il n'y aura pas trop de lecteurs en même temps. –