2011-07-06 1 views
3

Le documentation for dispatch_semaphore_wait indique qu'il "attend dans l'ordre FIFO pour un signal". Mais il ne semble pas dans cet exemple-- quelqu'un peut-il expliquer s'il vous plaît?Est-ce que dispatch_semaphore_wait n'est pas FIFO?

Exemple:

#include <dispatch/dispatch.h> 
#include <stdio.h> 

dispatch_queue_t q1, q2; 
dispatch_semaphore_t sem; 
int g_call; 

void do_work(void) 
{ 
    int s = 0; 
    int i; 
    for (i = 0; i < 100000000; ++i) 
     ++s; 
} 

void f1(int call) 
{ 
__block int waited = 0; 
    dispatch_async(q1, ^{ 
     while (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC/1000))) 
      waited = 1; 
     printf("1:%d %s\n", call, waited ? "waited" : ""); 
     do_work(); 
     dispatch_semaphore_signal(sem); 
    }); 
} 

void f2(int call) 
{ 
    __block int waited = 0; 
    dispatch_async(q2, ^{ 
     while (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC/1000))) 
      waited = 1; 
     printf("\t\t2:%d %s\n", call, waited ? "waited" : ""); 
     do_work(); 
     dispatch_semaphore_signal(sem); 
    }); 
} 

int main(int argc, char **argv) 
{ 
    q1 = dispatch_queue_create(NULL, NULL); 
    q2 = dispatch_queue_create(NULL, NULL); 
    sem = dispatch_semaphore_create(1); 
    g_call = 0; 

    dispatch_queue_t q_global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, q_global); 
    const uint64_t DELAY = 10; 
    dispatch_source_set_event_handler(timer, ^{ 
     f1(g_call); 
     f2(g_call); 
     ++g_call; 
     dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, DELAY), 0, 0); 
    }); 
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, DELAY), 0, 0); 
    dispatch_resume(timer); 

    sleep(3); 
} 

Résultats attendus:

1:0 
     2:0 
1:1 
     2:1 
1:2 
     2:2 
... 

sortie réelle (un exemple):

1:0 
1:1 
... 
1:14 
     2:0 waited 
     2:1 
     ... 

Modifier: puissance effective si, au lieu de files d'attente étant en série , q1 et q2 sont définis sur la file d'attente globale:

1:0 
     2:8 waited 
1:3 waited 
1:4 waited 
     2:3 waited 
1:6 waited 
1:9 waited 
     2:9 waited 
     2:21 
1:28 waited 

(Parfois, il fonctionne parfaitement, mais parfois, il est bizarre comme ça.)

Répondre

3

dispatch_queue_create crée une file d'attente de série, puis la file d'attente série crée un thread pthread (je ne suis pas si sûr ...). Et dispatch_semaphore_wait utilise des verrous spin pour l'acquisition d'un sémaphore pour les performances. Cela signifie que ce n'est pas un point de changement de contexte comme pthread_mutex_lock. Il ne change pas de contexte si souvent.

Si vous utilisez la file d'attente globale, votre code sortira comme prévu (mais ce n'est pas exactement la même chose). Parce que la file d'attente globale utilise pthread workqueue. Le comportement du contexte de commutation est différent de celui du thread pthread.

q1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
q2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

Edited:

La file d'attente globale exécute les l'ordre de sortie des tâches données séquentiellement, mais ces tâches sont exécutés en parallèle, peut varier par changement de contexte. De plus, la minuterie de votre code se déclenche toutes les 10 nanosecondes, trop de tâches s'exécutent simultanément.

Un autre exemple simple,

dispatch_queue_t queue = 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_apply(10, queue, ^(size_t index) { 
    printf("%zu\n", index); 
}); 

Sur mon MacBook Pro 8core:

4 
2 
0 
6 
3 
1 
5 
8 
9 
7 
+0

Merci pour le explanation-- qui aide. Mais si je fais q1 et q2 la file d'attente globale, parfois ça marche mais parfois les sorties sont totalement hors service. Voir mes modifications. Une idée de pourquoi cela se passe? (Je ne suis pas sûr que ce soit les sémaphores ou la file d'attente globale qui fait le réordonnancement.) – jlstrecker

+0

Mis à jour ma réponse. –