2009-12-08 2 views
3

Je suis complètement époustouflé par la qualité de l'implémentation de Windows SRW. Ses sections plus rapides que critiques et ses quelques octets de mémoire en surcharge.Existe-t-il une version multiplateforme des verrous d'écriture de lecteur slim de Windows Vista?

Malheureusement, il est uniquement Windows Vista/Windows 7.

Comme il est une implémentation de terre pure de l'utilisateur, quelqu'un sait s'il y a une implémentation multi-plateforme pour elle? Quelqu'un at-il inversé-ingénierie là solution?

Et s'il vous plaît je ne veux pas ajouter des trucs comme boost juste pour tirer dans une solution moins de 100 LOC.

Répondre

3

Si vous voulez quelque chose de "portable" dans le sens de se conformer à certaines normes ... Si vous utilisez des threads POSIX il y a pthread_rwlock_init() et amis. Ceux-ci ne sont bien sûr pas typiquement utilisés sur Windows mais plutôt sur les OS de type Unix. Mais si vous voulez dire "portable" dans le sens de "portable vers plusieurs versions de Windows ..." Il y a des appels non documentés dans ntdll qui implémentent des verrous RW. RtlAcquireResourceShared() et RtlAcquireResourceExclusive().

Voici quelques prototypes de WINE's implementation:

void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl); 
void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl); 
BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait); 
BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait); 
void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl); 

Remarque vous pouvez avoir à GetProcAddress() ceux-ci de ntdll.dll vous.

En ce qui concerne la structure référencée ... Voici ce que déclare VIN:

typedef struct _RTL_RWLOCK { 
    RTL_CRITICAL_SECTION rtlCS; 

    HANDLE hSharedReleaseSemaphore; 
    UINT uSharedWaiters; 

    HANDLE hExclusiveReleaseSemaphore; 
    UINT uExclusiveWaiters; 

    INT iNumberActive; 
    HANDLE hOwningThreadId; 
    DWORD dwTimeoutBoost; 
    PVOID pDebugInfo; 
} RTL_RWLOCK, *LPRTL_RWLOCK; 

Si vous ne voulez pas utiliser pthreads et vous ne voulez pas faire un lien vers une fonctionnalité non documentée ... Vous pouvez peu précis Recherchez une implémentation de rwlock et mettez-la en œuvre vous-même en termes d'autres opérations ... Dites InterlockedCompareExchange(), ou peut-être des primitives de niveau supérieur telles que des sémaphores et des événements.

+0

Eh bien, je ne veux pas d'appels système et ce n'est pas le code pour SRW. Ils sont rapides. Tout ce que je veux, c'est du code C/Assembler qui est en train de faire cette magie InterlockedCompareExchange. Cela devrait être par définition portable sur les plates-formes Intel i386 ou amd64 si la même syntaxe d'assembleur est utilisée. – Lothar

+0

Dans ce cas: http://www.google.com/search?q=rwlock+interlockedcompareexchange - Notez également que l'instruction x86 pour InterlockedCompareExchange() est "lock cmpxchg". – asveikau

+0

@Lothar - eh bien vous ne pouvez pas complètement éviter les appels système si vous voulez un blocage correct - c'est-à-dire, quand un thread ne peut pas acquérir le verrou, il doit aller se mettre en veille. L'appel système ne se produit que dans le cas contentieux - si vous ne voulez pas d'appel système, la seule option est de faire tourner la boucle, à peu près. J'ai ajouté une réponse ci-dessous qui décrit comment vous rouleriez le vôtre. – BeeOnRope

0

Vous pouvez certainement rouler les vôtres en utilisant les mêmes idées que slim rwlock (du moins ce que j'imagine qu'ils ont fait, puisque c'est assez simple). J'ai décrit l'approche en détail dans this other question. Pour votre cas, vous pouvez ignorer la plupart du temps l'aspect «équitable», mais l'implémentation est essentiellement la même. En particulier, si vous êtes prêt à laisser un flux indéfini de lecteurs bloquer les écrivains, vous laissez toujours les lecteurs lorsque le verrou a déjà des lecteurs dedans (c'est-à-dire, état (2) et (3) plus ou moins s'effondrer ensemble).

Dans votre cas, pour l'angle multiplate-forme, vous devez implémenter le blocage avec événements Windows ou pthread condvars - mais les détails sont similaires dans les deux cas. Ou, si vous voulez vraiment éviter de bloquer du tout, votre seul choix est de tourner (idéalement en utilisant l'instruction pause pour être agréable à la CPU), ce qui rend les choses encore plus faciles en supprimant tout le fallback au code de blocage.

Une bonne implémentation est probablement de quelques centaines de LOC. J'en ai écrit un (source proche, je ne peux pas le partager) et il fonctionne très bien (mieux que le verrou mince, en fait).

Questions connexes