pthread_once() — Invoke a function once
Standards
Standards / Extensions | C or C++ | Dependencies |
---|---|---|
POSIX.4a |
both | POSIX(ON) |
Format
#define _OPEN_THREADS
#include <pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void(*init_routine)());
#define _UNIX03_THREADS
#include <pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void(*init_routine)());
General description
Establishes a function that will be executed only once in a given process. You may have each thread call the function, but only the first call causes the function to run. This is true even if called simultaneously by multiple threads. For example, a mutex or a thread-specific data key must be created exactly once. Calling pthread_once() prevents the code that creates a mutex or thread-specific data from being called by multiple threads. Without this routine, the execution must be serialized so that only one thread performs the initialization. Other threads that reach the same point in the code are delayed until the first thread is finished.
pthread_once() is used in conjunction with a once control variable of the type pthread_once_t. This variable is a data type that you initialize to the PTHREAD_ONCE_INIT constant. It is then passed as a parameter on the pthread_once() function call.
init_routine is a normal function. It can be invoked directly outside of pthread_once(). In addition, it is the once_control variable that determines if the init_routine has been invoked. Calling pthread_once() with the same routine but with different once_control variables, will result in the routine being called twice, once for each once_control variable.
Returned value
If successful, pthread_once() returns 0.
If unsuccessful, pthread_once() returns -1.
There are no documented errno values. Use perror() or strerror() to determine the cause of the error.
Special behavior for Single UNIX Specification, Version 3: If unsuccessful, pthread_once() returns an error number to indicate the error.
Example
/* CELEBP46 */
#ifndef _OPEN_THREADS
#define _OPEN_THREADS
#endif
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#define threads 3
int once_counter=0;
pthread_once_t once_control = PTHREAD_ONCE_INIT;
void once_fn(void)
{
puts("in once_fn");
once_counter++;
}
void *threadfunc(void *parm)
{
int status;
int threadnum;
int *tnum;
tnum = parm;
threadnum = *tnum;
printf("Thread %d executing\n", threadnum);
status = pthread_once(&once_control, once_fn);
if ( status < 0)
printf("pthread_once failed, thread %d, errno=%d\n", threadnum,
errno);
pthread_exit((void *)0);
}
main() {
int status;
int i;
int threadparm[threads];
pthread_t threadid[threads];
int thread_stat[threads];
for (i=0; i<threads; i++) {
threadparm[i] = i+1;
status = pthread_create( &threadid[i],
NULL,
threadfunc,
(void *)&threadparm[i]);
if ( status < 0) {
printf("pthread_create failed, errno=%d", errno);
exit(2);
}
}
for ( i=0; i<threads; i++) {
status = pthread_join( threadid[i], (void *)&thread_stat[i]);
if ( status < 0)
printf("pthread_join failed, thread %d, errno=%d\n", i+1, errno);
if (thread_stat[i] != 0)
printf("bad thread status, thread %d, status=%d\n", i+1,
thread_stat[i]);
}
if (once_counter != 1)
printf("once_fn did not get control once, counter=%d",once_counter);
exit(0);
}
Thread 1 executing
in once_fn
Thread 2 executing
Thread 3 executing