linux-sysprog · beginner · ~10 min

One-shot init: which call performs the work?

The once-only semantics of pthread_once.

Challenge

Model the "run exactly once" rule of pthread_once: out of many threads that try to run the initializer, only the first one actually does. Here that reduces to finding the first attempt in an array.

Task

Implement int once_init_run_index(const int *calls, int n) that returns which call performs the one-time initialization.

Input

  • calls, n: an array where calls[i] == 1 means "a thread invoked pthread_once at index i" (0 means no invocation there).

Output

Returns the index of the first 1 in the array — that call runs init_fn; every later call is a no-op. Returns -1 if no call was made (all zeros, or empty).

Example

once_init_run_index({0,0,1,1,0,1}, 6)   ->   2   (first invocation)
once_init_run_index({1,1,1}, 3)         ->   0
once_init_run_index({0,0,0}, 3)         ->   -1  (never invoked)
once_init_run_index(NULL, 0)            ->   -1

Edge cases

  • All zeros or an empty/NULL array returns -1.
  • If the first element is 1, the answer is 0.

Why this matters

pthread_once is the canonical 'initialise this lazily, exactly once, across all threads' primitive. Tracing through its semantics builds intuition.

Input format

An array calls of n flags, where calls[i]==1 means a thread invoked pthread_once at index i.

Output format

The index of the first 1 (the call that runs init_fn), or -1 if there is none.

Constraints

Return the lowest index whose value is 1; -1 if all are 0 or n is 0.

Starter code

int once_init_run_index(const int *calls, int n) { /* TODO */ (void)calls; (void)n; return -1; }

Common mistakes

Returning the LAST call.

Edge cases to handle

All zeros. Empty array. First index is 1.

Complexity

O(n).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.