0

スレッドを使用してファイルからデータを読み取り、任意のサイズのバッファーに書き込むプログラムを実装しようとしていますが、他の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*));
4

1 に答える 1

1

コードをステップ実行していませんが、終端の NUL'\0'バイトを書き込んでおり、1 バイトのバッファー全体を占有します。ライターは、バッファー内のスペースを永遠に待ちます。

while ((b->writepos + 1) % numlines == b->readpos) { /* always satisfied */
于 2012-04-05T01:40:45.700 に答える