0

この質問は、この質問のフォローアップです。要約すると、サーバーがclose()を呼び出して接続を終了しましたが、シャットダウンシーケンスが発生しなかったかのように見えました。クライアントはさらにデータを待ち続けました。close()はサーバーで0を返しました。条件付きキューが正しく実装されていても、スレッドセーフキューを条件付き待機からセマフォに切り替えることで問題が解決しました。私は自分のコードを投稿して、誰かが私のためにこれらのことについて何か照明を持っているかどうかを確認しています。

条件ベースのキュー:

  TASK *head;
  pthread_mutex_t mutex;
  pthread_cond_t cond;

  void init( ) {
    head = NULL;
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
  }

  TASK *get( ) {
    pthread_mutex_lock( &mutex );
    while(!head)
      pthread_cond_wait(&cond, &mutex);
    TASK *res = head;
    head = head->next;
    pthread_mutex_unlock( &mutex );
    return res;
  }

  void add( TASK *t ) {
    pthread_mutex_lock( &mutex );
    t->next = head;
    head = t;
    pthread_cond_broadcast( &cond );
    pthread_mutex_unlock( &mutex );
  }

これはLIFOキューであり、次はFIFOであることに気付きましたが、興味深いビットのみを含めたので、すばやく読みやすくなっています。

セマフォベースのキュー:

  TASK *buf;
  TASK *next_reader;
  TASK *next_writer;
  TASK *endp;
  pthread_mutex_t writer_mutex;
  pthread_mutex_t reader_mutex;
  sem_t writer_sem;
  sem_t reader_sem;

  void init( int num_tasks ) {
    buf = calloc(sizeof(TASK), num_tasks);
    next_reader = buf;
    next_writer = buf;
    endp = buf + num_tasks;
    sem_init(&writer_sem, 0, num_tasks);
    sem_init(&reader_sem, 0, 0);
    pthread_mutex_init(&writer_mutex, NULL);
    pthread_mutex_init(&reader_mutex, NULL);
  }

  TASK *get( ) {
    TASK *res = NULL;
    sem_wait(&reader_sem);
    pthread_mutex_lock(&reader_mutex);
    res = next_reader;
    next_reader++;
    if(next_reader == endp)
      next_reader = buf;
    pthread_mutex_unlock(&reader_mutex);
    sem_post(&writer_sem);
    return res;
  }

  void add( TASK *t ) {
    sem_wait(&writer_sem);
    pthread_mutex_lock(&writer_mutex);
    *next_writer = *item;
    next_writer++;
    if(next_writer == endp)
      next_writer = buf;
    pthread_mutex_unlock(&writer_mutex);
    sem_post(&reader_sem);
  }

スレッドがソケットを閉じていて、閉じている間にpthread_cond_broadcastが呼び出された場合にファンキーなことが起こっていない限り、条件キューからセマフォキューへの変更が前の質問をどのように解決するかを一生見ることはできません。私がしていることを非難するドキュメントが見つからないため、OSのバグを想定しています。キューアクションはいずれもシグナルハンドラーから呼び出されません。これが私のディストリビューションです:

Linuxバージョン:2.6.21.7-2.fc8xen

Centosバージョン:5.4(最終版)

ありがとう

編集----私が行っている初期化に追加しました。実際のコードでは、これらはテンプレート化されたクラスに実装されています。関連する部分を含めました。

4

0 に答える 0