6 ex__parallel__for_8c
gullradriel edited this page 2026-10-09 00:55:18 +02:00

examples/ex_parallel_for.c

Functions

Name
void * nested(void * arg)
a loop run from another thread, as a pool worker would
int main(void )
void expect_true(const char * what, int ok)
report a check
void bump(size_t begin, size_t end, void * user)
add one to each item of the slice, so a slice done twice shows as a 2
int all_ones(const int * items, size_t count)
every item is exactly one

Attributes

Name
int failures
count of failed checks

Functions Documentation

function nested

static void * nested(
    void * arg
)

a loop run from another thread, as a pool worker would

function main

int main(
    void 
)

function expect_true

static void expect_true(
    const char * what,
    int ok
)

report a check

function bump

static void bump(
    size_t begin,
    size_t end,
    void * user
)

add one to each item of the slice, so a slice done twice shows as a 2

function all_ones

static int all_ones(
    const int * items,
    size_t count
)

every item is exactly one

Attributes Documentation

variable failures

static int failures = 0;

count of failed checks

Source code



#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "nilorea/n_common.h"
#include "nilorea/n_log.h"
#include "nilorea/n_thread_pool.h"

static int failures = 0;

static void expect_true(const char* what, int ok) {
    if (!ok) {
        n_log(LOG_ERR, "FAIL: %s", what);
        failures++;
    }
}

static void bump(size_t begin, size_t end, void* user) {
    int* items = (int*)user;
    size_t i = 0;

    for (i = begin; i < end; i++) items[i]++;
}

static void* nested(void* arg) {
    n_parallel_for(0, 1000000, 1000, bump, arg);
    return NULL;
}

static int all_ones(const int* items, size_t count) {
    size_t i = 0;

    for (i = 0; i < count; i++)
        if (items[i] != 1) return 0;
    return 1;
}

int main(void) {
    int* a = NULL;
    int* b = NULL;
    pthread_t other;
    int slices = 0;

    set_log_level(LOG_NOTICE);
    a = calloc(1000000, sizeof(int));
    b = calloc(1000000, sizeof(int));
    if (!a || !b) return 1;

    slices = n_parallel_for(0, 1000000, 1000, bump, a);
    n_log(LOG_NOTICE, "ex_parallel_for: a million items in %d slice(s) on %ld core(s)", slices, get_nb_cpu_cores());
    expect_true("every item written exactly once", all_ones(a, 1000000));
    expect_true("more than one slice on a machine with more than one core",
                get_nb_cpu_cores() < 2 || slices > 1);

    memset(a, 0, 1000000 * sizeof(int));
    expect_true("a range under two grains runs as one slice", n_parallel_for(0, 1500, 1000, bump, a) == 1);
    expect_true("and does all of it", all_ones(a, 1500));
    expect_true("an empty range does nothing", n_parallel_for(10, 10, 1, bump, a) == 0);
    expect_true("a NULL function does nothing", n_parallel_for(0, 10, 1, NULL, a) == 0);

    /* Two at once, sharing the budget. */
    memset(a, 0, 1000000 * sizeof(int));
    if (pthread_create(&other, NULL, nested, b) != 0) return 1;
    n_parallel_for(0, 1000000, 1000, bump, a);
    pthread_join(other, NULL);
    expect_true("two loops at once both finish right", all_ones(a, 1000000) && all_ones(b, 1000000));

    free(a);
    free(b);
    n_log(LOG_NOTICE, "ex_parallel_for: %s", failures ? "FAILED" : "ok");
    return failures ? 1 : 0;
}