C pthreads - threadpool - threads beenden

hell-student

Lieutenant
Registriert
Nov. 2007
Beiträge
671
Hallo Zusammen,

Ich habe einen Threadpool in C implementiert und füge Jobs in eine Linked List ein. Am Head nehme ich die Jobs wieder weg und bearbeite sie dann. Nun will ich mein Programm "fein" wieder aufräumen, aber meine Threads bleiben in der Endlosschleife. Folgender Code:

Worker Thread führt test_calculation aus:
Code:
void *invade_thread_worker(void *payload __attribute__((unused)))
{
	Job *job;
	status_t status;

	for(;;) {
		pthread_mutex_lock(&invade_job_mutex);
		while(!(job = head)) {
			pthread_cond_wait(&invade_job_cond, &invade_job_mutex);
                        
                        if (prog-stop) break;

		}

                if (prog-stop) break;
 
		head = head->next;
		pthread_mutex_unlock(&invade_job_mutex);

		// work on job
        if (job->status == PENDING) {
        	job->status = WORKING;
            status = test_calculation(job);

            if (job->status == WORKING) {
            	job->status = status;
            }

            if(job->status == SUCCESS) {
            }
            else if(job->status == CANCELED) {
            }
        }
	}

        //cleanupcode

	return NULL;
}

Einfügen neuer Jobs am Ende der Linked List:
Code:
void enqueue_job(int index)
{
	pthread_mutex_lock(&invade_job_mutex);
	add_to_list(index);
	pthread_cond_signal(&invade_job_cond);
	pthread_mutex_unlock(&invade_job_mutex);
}

Wenn ich nun mein Programm beenden will, hab ich wie gesagt das Problem, dass meine Threads wohl in ihrer While-Schleife hängen, da Head = NULL ist, also kein neuer Job hinzukommt. Wenn ich doch aber per cond_signal alle wartenden Threads wieder aufwecke, müssten die doch weiterlaufen und sich beenden.

Die Main wartet mittels pthread_join auf die Threads.

thx
 
Hi ;)

while(!(job = head)) -> möchtest du da zu weisen oder vergleichen?

Und in der Zeile 11-15 hättest du wohl das Problem das der Mutex nicht mehr freigegeben wird und somit die Restlichen Threads ewig warten.

Verschieben den Code aus Zeile 17 + 18 in die 14 und Teste das ganze nochmal.

somit wird der Mutex wieder freigegeben und die Nachfolgenden Threads werden nicht endlos blockiert.

Gruß
 
Zuletzt bearbeitet:
Danke für die Hilfe, habe aber noch etwas rumdocktern müssen, bis es nun wirklich klappt.. Leider habe ich gerade wieder ein Problem. Ich habe mehr als einen Thread. Sagen wir Thread A und Thread B sowie den Hauptthread Thread MAIN. Ich möchte nun mein Programm richtig aufräumen beim Beenden und dachte MAIN kann ja mit pthread_join auf A und B warten, bzw. den signalisieren, dass sie nichts mehr rechnen müssen und dannach auf deren Beendigung warten.

Code:
void threads_cleanup()
{
	int i;

	for (i = 0; i < NO_THREADS; i++) {
		pthread_mutex_lock(&job_mutex);
		pthread_cond_signal(&ijob_cond);
		pthread_mutex_unlock(&job_mutex);
		pthread_join(threads[i], NULL);
	}
}

Die Threads A und B arbeiten ja Jobs aus einer Linked List ab und legen sich schlafen, wenn kein Job da ist. Wenn mit threads_cleanup ihnen nun per sig mitgeteilt wird, dass sie wieder weiterarbeiten können und mittels "if (prog-stop) break;" wird deren Endlosschleifen beendet. Das Problem ist glaube ich, dass ich ja immer zuerst auf thread A warte, da i anfangs mit 0 beginnt. Wenn sich aber nun Thread B den Mutex nimmt und sich beendet, wartet der MAIN Thread unendlich lange, da Thread A immer noch Däumchen dreht. MAIN würde also immer in Zeile 9 hängen bleiben Wie kann ich mehrere Threads joinen bzw. dass deren Reihenfolge irrevelevant ist. thx
 
hell-student schrieb:
Das Problem ist glaube ich, dass ich ja immer zuerst auf thread A warte, da i anfangs mit 0 beginnt. Wenn sich aber nun Thread B den Mutex nimmt und sich beendet, wartet der MAIN Thread unendlich lange, da Thread A immer noch Däumchen dreht. MAIN würde also immer in Zeile 9 hängen bleiben Wie kann ich mehrere Threads joinen bzw. dass deren Reihenfolge irrevelevant ist. thx

Ich entschuldige mich schon mal im Voraus falls ich dein Problem falsch verstanden habe, aber wenn dein Thread gerade einen Mutex in Beschlag hat, muß er den natürlich noch freigeben, bevor er seine Thread-Funktion verläßt (und sich damit beendet). Statt

Code:
if (prog-stop) break;

würde ich also

Code:
if (prog-stop)
{
    pthread_mutex_unlock(&invade_job_mutex)
    break;
}

vorschlagen.
 
Hmm ich glaube ich hab mein Problem nicht genau genug erklärt bzw. viel zu umständlich. Die Funktion führt der Thread A und B aus:

Code:
for(;;) {
		pthread_mutex_lock(&invade_job_mutex);
		while(!(job = head)) {
			if (!rts_state) {
				break;
			}
			pthread_cond_wait(&invade_job_cond, &invade_job_mutex);
		}
		
		if (rts_state) {
			head = head->next;
		}
		
		pthread_mutex_unlock(&invade_job_mutex);

		if (!rts_state) {
			break;
		}

		printf("starte Job\n");

		// work on job
       
                printf("job beendet")
        }
	}

Jeder Thread (A bzw B) holt sich also den Mutex und gibt ihn auch wieder frei, wenn das Programm beendet werden soll. Im MAIN Thread warte ich mittels phread_join auf beide Threads, wie im Post zuvor beschrieben. Jedoch wird mein Programm nicht beendet.
 
Zeile 3: Wie bereits erwähnt, willst du höchstwahrscheinlich vergleichen und nicht zuweisen.
Zeile 5: Bei diesem break hat der Thread das Mutex noch immer in der Hand. Es muss vor dem Rücksprung freigegeben werden. Erwähnte ich in meinem letzten knappen Post. (pthread_cond_wait verlangt und versichert, dass bei Eintritt und Austritt das Mutex im "gelockten" Zustand ist)
 
Zurück
Oben