106
Implementacje operacji semaforowych na semaforze ogólnym, czyli operacji podnoszenia semafora (zwiększania wartości zmiennej semaforowej o 1) i operacji opuszczania semafora (zmniejszania wartości zmiennej semaforowej o 1), ilustruje poniższy przykład:
#include <sys/types.h> tinclude <sys/ipc.h>
#include <sys/sem.h> static struct sembuf buf; void podnieś (int semid, int semnuin) { buf.sem_num = semnum; buf.sem_op = 1; buf.sem_flg = 0;
if (semop(semid, &buf, 1) == —1){
perror("Podnoszenie semafora"); exit(1);
void opusc(int semid, int semnum){ bu f.s em_num = s emnum; buf.sem_op = -1;
•buf.sem_flg = 0;
if (semop(semid, &buf, 1) == -1){
perror("Opuszczenie semafora"); exit(1);
ł
Kod 9.4. Przykład implementacji operacji semaforowych
10
Wątek może także wyłączyć możliwość anulowania siebie za pomocą funkcji:
pthread_setcancelstatę(PTHREAD_CANCEL_DISABLE,NULL)
Pozwala ona na zrealizowanie sekcji krytycznej, czyli sekwencji kodu wykonywanego w całości bez przerwy aż do zakończenia. Aby przywrócić poprzednią wartość stanu anulowania, na końcu sekcji krytycznej zamiast ustawiania wartości PTHREAD_CANCEL_ENABLE, można wywołać funkcję process_transaction () z innej sekcji krytycznej. Używanie anulowania do kończenia wątków nie jest dobrym pomysłem, lepszą strategią jest przekazanie wątkowi informacji, że powinien się zakończyć.
Załóżmy, że program ma zestaw czekających w kolejce zadań, które są przetwarzane przez klika jednoczesnych wątków. Kolejka zadań realizowana jest za pomocą listy połączonej obiektów. Po zakończeniu działania każdy z wątków sprawdza kolejkę - jeśli wskaźnik nie jest pusty, wątek usuwa początek listy i ustawia wskaźnik na następne zadanie. Funkcja wątku mogłaby mieć następującą postać:
#include <malloc.h>
/* Elementy listy */ struct zadanie { struct zadanie* następny;
/* Pozostałe cola ... */
} ;
/* Lista dowiązaniowa zadań do wykonania */ struct zadanie* kolejka_zadan;
extern void przetwarzaj_zaaanie (struct zadanie*); void* funkcja_watku (void* arg)
{
while (kolejka_zaaan != NULL) {
struct zadanie* nastepne_zadar.ie = kolej ka_zadan,-kolejka_zadan = kolejka_zadan->nast; przetwarzaj_zadanie (nastepne_zadanie); free (nasteone_zaaanie);
}
return NULL;
}
Kod 10.1. Przykład funkcji wątku
!0 Na podstawie prac [6 i 8].