C: pthread специфичный для данных деструктор вызывается только один раз - PullRequest
4 голосов
/ 23 февраля 2009

С pthread_key_create manpage:

Дополнительная функция деструктора может быть связаны с каждым значением ключа. В выход из потока, если значение ключа имеет ненулевой указатель деструктора и поток имеет ненулевое значение с помощью клавиши функция указывает на вызывается с текущим связанным ценность в качестве единственного аргумента. порядок вызовов деструкторов не указано, если более одного деструктор существует для потока, когда это выходит.

Если после всех деструкторов есть был вызван для всех ненулевых значений с соответствующими деструкторами, есть все еще некоторые ненулевые значения с связанные деструкторы, то Процесс повторяется. Если после минимум [PTHREAD_DESTRUCTOR_ITERATIONS] итерации деструктора выдающиеся ненулевые значения, там все еще некоторые ненулевые значения с связанные деструкторы, реализация перестает звонить деструкторов.

Я написал небольшой пример с простым деструктором, печатающим «Hello World» для значения, не относящегося к NULL-потоку. Насколько я могу видеть, этот деструктор вызывается только один раз (по крайней мере, в linux fedora и mac os x), даже если специфическое для потока значение все еще не равно NULL после первого вызова деструктора.

Я что-то пропустил ?! (PTHREAD_DESTRUCTOR_ITERATIONS = 4 для glibc.)

Вот мой маленький пример:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NB_THREADS 1
#define NB_KEYS 1

static pthread_key_t keys[NB_KEYS];
static pthread_mutex_t mutex;

void destruction (void *arg)
{
  (int) arg ++;
  printf ("Destructor called! -- key value : %i\n", (int)arg);
}

void* startup_routine(void* argv)
{
  int i;
  int th = (int) argv;

  for (i = 0; i < NB_KEYS; i++)
    pthread_setspecific(keys[i], (void*) ((th + i)* 2));

  pthread_mutex_lock(&mutex);

  printf("Thread %i\n", th);

  for (i = 0; i < NB_KEYS; i++)
    printf ("\tkeys[%i] : %i\n", i, (int)pthread_getspecific(keys[i]));

  pthread_mutex_unlock(&mutex);

  return "End";
}

int main(int argc, char** argv)
{
  int i;
  void *result;
  pthread_t thread[NB_THREADS];

  for (i = 0; i < NB_KEYS; i++)
    pthread_key_create(&keys[i], destruction);

  pthread_mutex_init(&mutex, NULL);

  for (i = 0; i < NB_THREADS; i++)
    pthread_create( &thread[i], NULL, startup_routine, (void*)(i+1) );

  for (i = 0; i < NB_THREADS; i++)
  {
    pthread_join( thread[i], &result );
    printf("Return from the thread %i = '%s'\n", i, (char*)result );
  }

  return 0;
}

Ответы [ 2 ]

3 голосов
/ 23 февраля 2009

Кажется, здесь не так много людей, использующих pthread!

Итак, я снова отвечу на свой вопрос:

Деструктор будет вызываться более одного раза ТОЛЬКО, если в деструкторе выполняется вызов pthread_setspecific, изменяющий значение ключа.

Это потому, что перед вызовом деструктора указатель ключа устанавливается в ноль, и указатель передается деструктору. Поэтому, если мы хотим, чтобы указатель на клавишу не был нулевым, просто нужно вызвать в нем pthread_setspecific.

0 голосов
/ 14 января 2010

Я не понимаю тайну. У вас есть только 1 ключ, специфичный для потока, и только 1 поток, который устанавливает данные, специфичные для потока. Поэтому деструктор должен выполняться только один раз, как и ожидалось.

Если вы установите специфичные для потока данные где-то после pthread_create () в main (), то деструктор будет вызываться дважды - один раз для дочернего потока и один раз для потока, связанного с main ().

...