15 /*

16 * One-time initialization routine used with the pthread_once

17 * control block.

18 */

19 void once_routine (void)

20 {

21  int status;

22

23  printf ('initializing key ');

24  status = pthread_key_create (&tsd_key, NULL);

25  if (status != 0)

26  err_abort (status, 'Create key');

27 }

28

29 /*

30 * Thread start routine that uses pthread_once to dynamically

31 * create a thread-specific data key.

32 */

33 void *thread_routine (void *arg)

34 {

35  tsd_t *value;

36  int status;

37

38  status = pthread_once (&key_once, once_routine);

39  if (status != 0)

40  err_abort (status, 'Once init');

41  value = (tsd_t*)malloc (sizeof (tsd_t));

42  if (value == NULL)

43  errno_abort ('Allocate key value');

44  status = pthread_setspecific (tsd_key, value);

45  if (status != 0)

46  err_abort (status, 'Set tsd');

47  printf ('%s set tsd value %p ', arg, value);

48  value->thread_id = pthread_self ();

49  value->string = (char*)arg;

50  value = (tsd_t*)pthread_getspecific (tsd_key);

51  printf ('%s starting... ', value->string);

52  sleep (2);

53  value = (tsd_t*)pthread_getspecific (tsd_key);

54  printf ('%s done... ', value->string);

55  return NULL;

56 }

57

58 void main (int argc, char *argv[])

59 {

60  pthread_t threadl, thread2;

61  int status;

62

63  status = pthread_create (

64  &thread1, NULL, thread_routine, 'thread 1');

65  if (status != 0)

66  err_abort (status, 'Create thread 1');

67  status = pthread_create (

68  &thread2, NULL, thread_routine, 'thread 2');

69  if (status != 0)

70  err_abort (status, 'Create thread 2');

71  pthread_exit (NULL);

72 }

Pthreads allows you to destroy a thread-specific data key when your program no longer needs it, by calling pthread_key_delete. The Pthreads standard guarantees only 128 thread-specific data keys at any one time, so it may be useful to destroy a key that you know you aren't using and won't need again. The actual number of keys supported by your Pthreads system is specified by the value of the symbol PTHREAD_KEYS_MAX defined in <limits.h>.

When you destroy a thread-specific data key, it does not affect the current value of that key in any thread, not even in the calling thread. That means your code is completely responsible for freeing any memory that you have associated with the thread-specific data key, in all threads. Of course, any use of the deleted thread-specific data key (pthread_key_t) results in undefined behavior.

Delete thread-specific data keys only when you are sure no thread has a value for that key!

Or,.. don't destroy them at all.

You should never destroy a key while some thread still has a value for that key. Some later call to pthread_key_create, for example, might reuse the pthread_key_t identifier that had been assigned to a deleted key. When an existing thread that had set a value for the old key requests the value of the new key, it will receive the old value. The program will likely react badly to receiving this incorrect data, so you should never delete a thread- specific data key until you are sure that no existing threads have a value for that key, for example, by maintaining a 'reference count' for the key, as shown in the program tsd_destructor.c. in Section 5.4.3.

Even better, don't destroy thread-specific data keys. There's rarely any need to do so, and if you try you will almost certainly run into difficulties. Few programs will require even the minimum Pthreads limit of 128 thread- specific data keys. Rarely will you use more than a few. In general, each component that uses thread-specific data will have a small number of keys each maintaining pointers to data structures that contain related data. It would take a lot of components to exhaust the available keys!

5.4.2 Using thread-specific data

int pthread_setspecific (pthread_key_t key, const void *value);

void *pthread_getspecific (pthread_key_t key);

You can use the pthread_getspecific function to determine the thread's current value for a key, or pthread_setspecific to change the current value. Take a look at Section 7.3.1 for ideas on using thread-specific data to adapt old libraries that rely on static data to be thread-safe.

A thread-specific data value of NULL means something special to Pthreads—do not set a thread-specific data value of NULL unless you really mean it.

The initial value for any new key (in all threads) is NULL. Also, Pthreads sets the thread-specific data value for a key to NULL before calling that key's destructor (passing the previous value of the key) when a thread terminates[4]. If your thread-specific data value is the address of heap storage, for example, and you want to free that storage in your destructor, you must use the argument passed to the destructor rather than calling pthread_getspecific.

Pthreads will not call the destructor for a thread-specific data key if the terminating thread has a value of NULL for that key. NULL is special, meaning 'this key has no value.' If you ever use pthread_setspecific to set the value

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату