Subj : Did pthread_once init_routine succeed? To : comp.programming.threads From : Ian Pilcher Date : Wed Feb 23 2005 05:19 pm Is it safe to use a file-scope variable to report the result of an init_routine called via pthread_once? I believe that it is, if the following conditions are met: * The variable is only set by the init_routine. * The variable is only read immediately following a call to pthread_once (with the appropriate parameters). It seems to me that one of three things can happen when a thread hits a call to pthread_once: 1. The thread is the "first" to call pthread_once (with these parameters). It will execute the init_routine, which sets the value of the variable, and then return from pthread_once. The value of the variable is determinate when the thread reads it. 2. The thread is not the "first" to call pthread_once, but the init_routine has not yet returned (in whatever thread it is executing). The thread will block until the other thread completes the init_routine (setting the variable). The value of the variable is determinate when the thread reads it. 3. The thread is not the "first" to call pthread_once, and init_routine has already completed (in this or another thread). The variable was set by init_routine, so its value is determinate when the thread reads it. Am I missing something? Thanks! (Concrete example follows.) #define _XOPEN_SOURCE 500 #include #include #include static int flag = 0; static pthread_rwlock_t lock; static pthread_once_t lock_once = PTHREAD_ONCE_INIT; static int lock_init_rv = -1; static void lock_init(void) { int pt_errno; if ((pt_errno = pthread_rwlock_init(&lock, NULL)) != 0) { fprintf(stderr, "Error %d initializing flag lock\n", pt_errno); return; } lock_init_rv = 0; } int get_flag(int *out) { int pt_errno; pthread_once(&lock_once, lock_init); if (lock_init_rv != 0) { fprintf(stderr, "Flag lock initialization failed\n"); return -1; } if ((pt_errno = pthread_rwlock_rdlock(&lock)) != 0) { fprintf(stderr, "Error %d locking flag for reading\n", pt_errno); return -1; } *out = flag; if ((pt_errno = pthread_rwlock_unlock(&lock)) != 0) { fprintf(stderr, "Error %d unlocking flag\n", pt_errno); return -1; } return 0; } int set_flag(int in) { int pt_errno; pthread_once(&lock_once, lock_init); if (lock_init_rv != 0) { fprintf(stderr, "Flag lock initialization failed\n"); return -1; } if ((pt_errno = pthread_rwlock_wrlock(&lock)) != 0) { fprintf(stderr, "Error %d locking flag for writing\n", pt_errno); return -1; } flag = in; if ((pt_errno = pthread_rwlock_unlock(&lock)) != 0) { fprintf(stderr, "Error %d unlocking flag\n", pt_errno); return -1; } return 0; } -- ======================================================================== Ian Pilcher i.pilcher@comcast.net ======================================================================== .