スレッドを使用してファイルからデータを読み取り、任意のサイズのバッファーに書き込むプログラムを実装しようとしていますが、他の2つのスレッドはこのバッファーから情報を読み取ります。バッファサイズを1に指定した場合を除いて、すべて正常に動作します。指定すると、すべてがロックされます。私は多かれ少なかれここからの古典的な「消費者/生産者」の例を適応させていますこれが私のコードです:
私が使用している構造体:
struct prodcons {
char** buffer; pthread_mutex_t lock;
pthread_cond_t notempty; pthread_cond_t notfull;
int readpos, writepos, finished;
};
私の「バッファに追加」スレッド
static void buf_add(struct prodcons *b, char* data) {
/* Add the data after locking the buffer */
pthread_mutex_lock(&b-> lock);
printf("Reader adding %s\n", data);
int err;
/*Wait until buffer is not full*/
while ((b->writepos + 1) % numlines == b->readpos) {
err = pthread_cond_wait(&b->notfull, &b->lock);
if (err != 0) { fprintf(stderr, "cond wait");}
}
/* Needed to stop writes */
if (data != NULL) {
b->buffer[b->writepos] = strdup(data);
} else {
//fprintf(stderr, "End of file reached, adding NULL\n");
b->buffer[b->writepos] = NULL;
}
/* Increments the writing position */
(*b).writepos++;
if ((*b).writepos >= numlines) {
printf("Resetting write position\n");
(*b).writepos = 0;
}
/* Unlock */
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
出力は次のようになります。
Reader adding 64.233.173.85
そして、それはただハングします。最初のwhileループを超えることは決してないことは明らかです。他のサイズでは機能しますが、1では機能しません。これに対する修正を実装する最良の方法は何でしょうか。これが役立つ場合は、これが私の「バッファから取得」メソッドです。
static void *read_from_buffer(struct prodcons *b) {
pthread_mutex_lock(&b -> lock);
/* We have to wait for the buffer to have something in it */
while ((*b).writepos == (*b).readpos) {
pthread_cond_wait(&b->notempty, &b->lock);
}
/* Set the thread delay */
thread_delay.tv_sec = threaddelay / 100000;
thread_delay.tv_nsec = 1000*threaddelay%100000;
char *t = NULL;
/* Read the data and advance the reader pointer */
if ((*b).buffer[(*b).readpos] != NULL) {
t = (char*)malloc(strlen ((*b).buffer[(*b).readpos] ) + 1);
strcpy(t, (*b).buffer[(*b).readpos]);
printf("Consumer %u reading from buffer: got %s\n", (unsigned int)pthread_self(), t);
/*At this point, we should probably check is FQDN*/
if (strcmp(t, "-1") == 0) {
(*b).finished = 1;
} else {
nanosleep(&thread_delay, &thread_delay_rem);
check_cache(t, &cache);
}
}
/* We have to adjust the reading position */
(*b).readpos++;
if ( (*b).readpos >= numlines) {
(*b).readpos = 0;
}
/*Need to signal and unlock */
pthread_cond_signal (&b->notfull);
pthread_mutex_unlock(&b->lock);
return t;
}
このエッジケースを処理するためのかなり簡単な修正があると確信していますが、私はそれを理解できないようです。任意の提案をいただければ幸いです!
編集:私も次のようにバッファを初期化します:
static void init(struct prodcons *temp) {
(*temp).buffer = (char**)malloc(numlines * sizeof(char*));