|
Thread-Specific Data
in Pthreads |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)
key
|
A key that can be used to obtain thread-specific data |
destructor
|
The function to call to free the thread-specific memory (or NULL if no destructor is needed) |
| Return | 0 on success; a positive error number on error |
Note: destructor() will be invoked automatically by the
system when the thread terminates (and passed the address of the
thread-specific memory for this key).
int pthread_setspecific(pthread_key_t key, const void *value)
key
|
The key used to identify the thread-specific data |
value
|
The value to save (which is normally a block of memory that has been previously allocated by the caller) |
| Return | 0 on success; a positive error number on error |
#include "grader.h"
#include <string.h>
char
*letter_grade(float number_grade)
{
char letter[2];
if (number_grade >= 90.0) strncpy(letter, "A", 1);
else if (number_grade >= 80.0) strncpy(letter, "B", 1);
else if (number_grade >= 70.0) strncpy(letter, "C", 1);
else if (number_grade >= 60.0) strncpy(letter, "D", 1);
else strncpy(letter, "F", 1);
letter[1] = '\0';
return letter;
}
A Driver with Multiple Threads
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "grader.h"
static void
*thread_entry(void *arg)
{
float number_grade = *(float *)arg;
//void *result = (void *)letter_grade(number_grade);
//return result;
printf("Thread: %s\n", letter_grade(number_grade));
return NULL;
}
int
main(void)
{
char *letter_main;
float number_helper;
pthread_t exam_helper;
// Calculate one letter grade in the main thread
letter_main = letter_grade(85.5);
// Calculate (and print) another letter grade in the helper thread
number_helper = 48.0;
pthread_create(&exam_helper, NULL, thread_entry, &number_helper);
// Terminate the helper thread
pthread_join(exam_helper, NULL);
// Now that the helper thread has terminated, print the
// grade that was calculated in the main thread
printf("Main: %s\n", letter_main);
return 0;
}
#include "grader.h"
#include <string.h>
char
*letter_grade(float number_grade)
{
static char letter[2];
if (number_grade >= 90.0) strncpy(letter, "A", 1);
else if (number_grade >= 80.0) strncpy(letter, "B", 1);
else if (number_grade >= 70.0) strncpy(letter, "C", 1);
else if (number_grade >= 60.0) strncpy(letter, "D", 1);
else strncpy(letter, "F", 1);
letter[1] = '\0';
return letter;
}
#include "grader.h"
#include <string.h>
static char letter[2];
char
*letter_grade(float number_grade)
{
if (number_grade >= 90.0) strncpy(letter, "A", 1);
else if (number_grade >= 80.0) strncpy(letter, "B", 1);
else if (number_grade >= 70.0) strncpy(letter, "C", 1);
else if (number_grade >= 60.0) strncpy(letter, "D", 1);
else strncpy(letter, "F", 1);
letter[1] = '\0';
return letter;
}
#include "grader.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static pthread_key_t grader_key;
static pthread_once_t grader_once = PTHREAD_ONCE_INIT;
static
void free_memory(void *buffer)
{
free(buffer);
}
static
void create_key(void)
{
pthread_key_create(&grader_key, free_memory);
}
char
*letter_grade(float number_grade)
{
char *letter;
// The first caller must create the key for the thread-specific data
pthread_once(&grader_once, create_key);
// Get the memory for the key
letter = pthread_getspecific(grader_key);
// If this is the first call from this thread then the memory
// will be NULL and, hence, must be allocated (and saved)
if (letter == NULL)
{
letter = malloc(2);
pthread_setspecific(grader_key, letter);
}
if (number_grade >= 90.0) strncpy(letter, "A", 1);
else if (number_grade >= 80.0) strncpy(letter, "B", 1);
else if (number_grade >= 70.0) strncpy(letter, "C", 1);
else if (number_grade >= 60.0) strncpy(letter, "D", 1);
else strncpy(letter, "F", 1);
letter[1] = '\0';
return letter;
}