pthread_once(3T) DG/UX 5.4R3.00 pthread_once(3T)
NAME
pthreadonce - initialize a package dynamically
SYNOPSIS
#include <pthread.h>
pthreadoncet oncecontrol = PTHREADONCEINIT;
int pthreadonce(pthreadoncet *oncecontrol, void
(*initroutine)());
where:
oncecontrol Pointer to the pthreadoncet object used to
synchronize initialization
initroutine Pointer to the initialization routine to be executed
once
DESCRIPTION
The first call to pthreadonce() by any thread in a process, with a
given oncecontrol, calls initroutine with no arguments. Subsequent
calls to pthreadonce() will not call initroutine(). On return from
pthreadonce() it is guaranteed that initroutine() has completed.
If multiple threads simultaneously call pthreadonce() with the same
oncecontrol, one thread will execute the initroutine and the others
will block until the first thread has completed the initialization.
The oncecontrol parameter is used to determine whether the
associated routine has been called. The application declares a
single pthreadoncet for each routine and (typically) statically
initializes it to the value of PTHREADONCEINIT defined in
<pthread.h>. The application calls pthreadonce(), always passing a
pointer to this variable in oncecontrol, along with initroutine.
The behavior of pthreadonce() is undefined if oncecontrol has
storage class automatic or is not initialized.
DIAGNOSTICS
Returns
pthreadonce() always returns 0. It never fails by returning -1. If
an unexpected failure occurs (for example, oncecontrol points to an
uninitialized or corrupted once-control variable), the manifestation
of the failure is undefined.
Errors
None.
SEE ALSO
pthreadcreate(3T). pthreadmutexlock(3T).
NOTES
In general, it is advisable to initialize packages at the beginning
of a program in order to avoid use of this function. Up-front
initialization is cleaner and typically less error-prone than dynamic
initialization.
Licensed material--property of copyright holder(s) 1
pthread_once(3T) DG/UX 5.4R3.00 pthread_once(3T)
However, some libraries may insist on performing dynamic
initialization. That is, the global initialization for the library
is performed when the first procedure in the library is called. In a
single-threaded program this is normally implemented using a static
variable whose value is checked on entry to routine, like this:
static int randomisinitialized = 0;
extern int initializerandom();
int randomfunction()
{
if (randomisinitialized == 0) {
initializerandom();
randomisinitialized = 1;
}
... /* operations performed after initialization */
}
To keep the same structure in a multi-threaded program a new
primitive is needed. Otherwise, the library must be accomplished by
an explicit call to a library exported function prior to any use of
the library.
For dynamic library initialization in a multi-threaded process a
simple flag is not sufficient; the flag must be protected against
modification by multiple threads simultaneously calling into the
library. Protecting the flag requires the use of a mutex; however,
mutexes must be initialized before they are used. Ensuring that the
mutex is only initialized once requires a recursive solution to this
problem.
The example above then becomes:
#include <pthread.h>
static pthreadoncet randomisinitialized = PTHREADONCEINIT;
extern int initializerandom();
int randomfunction()
{
(void) pthreadonce(&randomisinitialized, initializerandom);
... /* operations performed after initialization */
}
Licensed material--property of copyright holder(s) 2