pthread_once() — Invoke a function once

Standards

Standards / Extensions C or C++ Dependencies
POSIX.4a
Single UNIX Specification, Version 3
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)());
SUSV3:
#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
/* 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);                                                                       
}                                                                               
Output:
Thread 1 executing
in once_fn
Thread 2 executing
Thread 3 executing

Related information