RUN_ONCE(9)

RUN_ONCE(9) | Kernel Developer's Manual | RUN_ONCE(9)

# NAME

`RUN_ONCE`, `INIT_ONCE`, `FINI_ONCE` —
run a function exactly once

# SYNOPSIS

`#include <sys/once.h>`

ONCE_DECL(control);

int
`RUN_ONCE`(once_t *control, int (*init_func)(void));

int
`INIT_ONCE`(once_t *control, int (*init_func)(void));

void
`FINI_ONCE`(once_t *control, void (*fini_func)(void));

# DESCRIPTION

`RUN_ONCE`() provides a functionality similar to pthread_once(3). It ensures that, for a given control, `init_func`() is executed (successfully) exactly once. It is considered as a successful execution if and only if `init_func`() returned 0. As long as there was no successful execution, `RUN_ONCE`() will try again each time it is called.

`RUN_ONCE`() can sleep if it's called concurrently.

`INIT_ONCE`() is used in pair with `FINI_ONCE`(). `INIT_ONCE`() will only be run once similar to `RUN_ONCE`(). `FINI_ONCE`() will only be run at last time if it is called as many times as calling `INIT_ONCE`(). When `FINI_ONCE`() is executed, the next call to `INIT_ONCE`() will be executed again. That is, `INIT_ONCE`() and `FINI_ONCE`() can be nested.

# RETURN VALUES

On failure, `RUN_ONCE`() returns what `init_func`() returned. Otherwise, it returns 0.

# EXAMPLES

The following example shows how `RUN_ONCE`() is used. Regardless of how many times `some_func`() is executed, `init_func`() will be executed exactly once.

    static int
    init_func(void)
    {

    	/*
    	 * do some initialization.
    	 */

    	return 0; /* success */
    }

    int
    some_func(void)
    {
    	static ONCE_DECL(control);

    	RUN_ONCE(&control, init_func);

    	/*
    	 * we are sure that init_func has already been completed here.
    	 */
    }

# SEE ALSO

pthread_once(3), condvar(9), intro(9)

March 19, 2019 | NetBSD 10.1