例 4-14 のデータ構造は、条件変数による「生産者 / 消費者」問題のコード例 (例 4-11 参照) のデータ構造と似ています。2 つのセマフォでそれぞれ、バッファの使用済スロット数と未使用スロット数を表します。これらのセマフォは、未使用スロットができるまで生産者を待たせ、使用済スロットができるまで消費者を待たせます。
typedef struct {
char buf[BSIZE];
sem_t occupied;
sem_t empty;
int nextin;
int nextout;
sem_t pmut;
sem_t cmut;
} buffer_t;
buffer_t buffer;
sem_init(&buffer.occupied, 0, 0);
sem_init(&buffer.empty,0, BSIZE);
sem_init(&buffer.pmut, 0, 1);
sem_init(&buffer.cmut, 0, 1);
buffer.nextin = buffer.nextout = 0;
|
ここでは、もう一組の (バイナリ) セマフォを使用しています。これは 2 値型セマフォで、相互排他ロック (mutex ロック) と同じ働きをします。この 2 つのセマフォは、複数の生産者と複数の未使用スロットが存在する場合と、複数の消費者と複数の使用済みスロットが存在する場合に、バッファへのアクセスを制御します。本来このような場合では mutex を使用すべきですが、セマフォの使用例を示すために特に使用しています。
void producer(buffer_t *b, char item) {
sem_wait(&b->empty);
sem_wait(&b->pmut);
b->buf[b->nextin] = item;
b->nextin++;
b->nextin %= BSIZE;
sem_post(&b->pmut);
sem_post(&b->occupied);
}
|
char consumer(buffer_t *b) {
char item;
sem_wait(&b->occupied);
sem_wait(&b->cmut);
item = b->buf[b->nextout];
b->nextout++;
b->nextout %= BSIZE;
sem_post(&b->cmut);
sem_post(&b->empty);
return(item);
}
|