2017-07-27 3 views
3

Ich habe eine Logik in einer dynamischen Bibliothek, die einen Dienst ausführt, der von der Hauptprogrammdatei angefordert wird.Wie man vermeidet, auf pthread_cond_t zu warten, wo das Signal bereits gesendet wurde

Wenn Sie aus dem Bibliothekscode start_service anrufen, müssen einige Vorbereitungen getroffen werden, bevor der Dienst betriebsbereit ist. Während dieser Zeit sollte der Hauptcode nicht versuchen, auf den Dienst zuzugreifen.

Um den Hauptcode zu benachrichtigen, wenn der Dienst bereit ist, verwende ich bedingte Variable und signalisiere die Hauptdatei.

Ich möchte einige Ratschläge über die beste Möglichkeit, eine Situation zu behandeln, wenn die Bibliothek vor dem Haupt-Code warten auf die bedingte Variable zu behandeln. in diesem Fall kann die Warte ewig dauern ...

hier ist der Service-Code:

extern pthread_cond_t cnd; 
extern pthread_mutex_t mtx; 

void start_service() 
{ 
    // getting serviceable.  
    pthread_cond_signal(&cnd); 
    main_loop(); 
} 

Und hier ist der Hauptcode.

pthread_cond_t cnd; 
pthread_mutex_t mtx; 

int main() 
{  
    pthread_cond_init(&cnd,NULL); 
    pthread_mutex_init(&mtx, NULL); 

    std::thread mytrd(&start_service); 
    ... 
    pthread_mutex_lock(&mtx); 

    pthread_cond_wait(&cnd, &mtx); // what happens if we get here after the signal already sent. 
    pthread_mutex_unlock(&mtx); 
    ... 
} 

P.S das gewünschte Verhalten sollte sein, dass die Haupt-Code zu vermeiden für die bedingte Variable warten, wenn es bereits signalisiert hat.

+0

Sie können eine Semaphore mit anfänglicher Anzahl von '0' verwenden, so Haupt blockiert wird, bis 'start_service()' Erhöhung Semaphore Zahl auf '1'.If vor dem Bausteinaufruf im Haupt,' start_service() 'erhöht die Semaphorzahl auf' 1', main wird niemals in den Wartezustand gehen. –

+0

hi und danke für deinen Kommentar, es scheint wie ein passender Weg .. vielleicht kannst du meinen Code ändern, um deine Idee auszudrücken? – Zohar81

+0

pthread_wait ** muss immer ** in einer Schleife verwendet werden, die die Bedingung hat, auf die sie wartet. Keine Schleife zu verwenden ist eine schlechte Übung, sie kann jederzeit fehlschlagen. – geza

Antwort

2

Sie benötigen ein Prädikat und umschließen den wait in einer Prüfung für das Prädikat:

pthread_mutex_lock(&mtx); 
    while(! predicate) pthread_cond_wait(&cnd, &mtx); 
    pthread_mutex_unlock(&mtx); 

Auf diese Weise startet der Thread tut Ereignis zu warten, wenn es brauchen tut. Der zweite Grund, den Sie brauchen, ist die Vermeidung von ungewollten Wakeups, dh pthread_cond_wait kann zurückkommen, auch wenn der andere Thread den Zustand nicht signalisiert hat.

Der andere Thread hat dann zu tun (Sie müssen den Mutex sperren, das Prädikat zu schützen):

pthread_lock_mutex(&mtx); 
predicate = true; 
pthread_cond_signal(&cnd); 
pthread_unlock_mutex(&mtx); 
+0

das Prädikat sollte globale Variable genau wie mtx und cnd, oder? – Zohar81

+1

@ Sohar81: ja. Aber noch besser, packen Sie diese Dinge in eine Struktur und übergeben Sie sie als Parameter an den Thread. Auf diese Weise vermeiden Sie globale Variablen, und Sie können mehr Dienste haben. – geza

+0

@ Zohar81 Wenn Sie Zugriff auf C++ 11 haben, sollten Sie '' verwenden und wenn nicht, dann ''. Zumindest sollten Sie eine Bereichssperre verwenden, die den 'pthread_mutex_lock' im Konstruktor und den' pthread_mutex_unlock' im Destruktor ausführt. Auf diese Weise können Sie nicht vergessen, es zu entsperren (oder es im Falle einer Ausnahme zu sperren) – user463035818

2

Sie eine Semaphore mit anfänglicher Anzahl von 0 verwenden können, so main blockiert wird, bis start_service() Anstieg Semaphore zählen zu 1. Wenn vor dem Block Anruf in main, start_service() erhöht die Semaphor-Zählung zu 1, Haupt wird nie in Wartezustand eintreten.Etwas wie unten.

void start_service() 
{ 
    // getting serviceable.  
    sem_post(&sem_mutex);//increases to 1 
    main_loop(); 
} 
int main() 
{ 
    sem_init(&sem_mutex, 0, 0);//initially blocked. 
    std::thread mytrd(&start_service); 
    sem_wait(&sem_mutex); 
    ... 
} 
Verwandte Themen