1 ex__parallel__team_8c
gullradriel edited this page 2026-10-29 20:54:40 +01:00

examples/ex_parallel_team.c

Structures

Name
struct SHARER
what sharer() needs
struct NESTED
what nested() needs

Functions

Name
void * sharer(void * arg)
loops run from a second thread on a shared team
void nested(size_t begin, size_t end, void * user)
a slice that starts a loop of its own on the same team
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_equal(const int * items, size_t count, int value)
every item is exactly value

Attributes

Name
int failures
count of failed checks

Functions Documentation

function sharer

static void * sharer(
    void * arg
)

loops run from a second thread on a shared team

function nested

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

a slice that starts a loop of its own on the same team

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_equal

static int all_equal(
    const int * items,
    size_t count,
    int value
)

every item is exactly value

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 int all_equal(const int* items, size_t count, int value) {
    size_t i = 0;

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

typedef struct {
    N_PARALLEL_TEAM* team;
    int* items;
    size_t count;
} NESTED;

static void nested(size_t begin, size_t end, void* user) {
    NESTED* n = (NESTED*)user;
    size_t i = 0;

    for (i = begin; i < end; i++)
        n_parallel_team_run(n->team, 0, n->count, 1, bump, n->items + i * n->count);
}

typedef struct {
    N_PARALLEL_TEAM* team;
    int* items;
} SHARER;

static void* sharer(void* arg) {
    SHARER* s = (SHARER*)arg;
    int i = 0;

    for (i = 0; i < 100; i++) n_parallel_team_run(s->team, 0, 100000, 100, bump, s->items);
    return NULL;
}

int main(void) {
    N_PARALLEL_TEAM* team = NULL;
    N_PARALLEL_TEAM* solo = NULL;
    int* a = NULL;
    int* b = NULL;
    int* inner = NULL;
    int i = 0, first = 0, same = 1;
    pthread_t other;
    SHARER share;
    NESTED nest;

    set_log_level(LOG_NOTICE);
    a = calloc(100000, sizeof(int));
    b = calloc(100000, sizeof(int));
    inner = calloc(16 * 64, sizeof(int));
    team = n_parallel_team_new(4);
    expect_true("a team of four", team && n_parallel_team_size(team) == 4);
    if (!a || !b || !inner || !team) {
        free(a);
        free(b);
        free(inner);
        n_parallel_team_free(&team);
        return 1;
    }

    /* many short loops, each item once per loop */
    for (i = 0; i < 1000; i++) {
        int slices = n_parallel_team_run(team, 0, 100000, 100, bump, a);
        if (i == 0) first = slices;
        if (slices != first) same = 0;
    }
    expect_true("every item written once per loop", all_equal(a, 100000, 1000));
    expect_true("four slices every time", same && first == 4);

    memset(a, 0, 100000 * sizeof(int));
    expect_true("a range under two grains runs as one slice", n_parallel_team_run(team, 0, 150, 100, bump, a) == 1);
    expect_true("and does all of it", all_equal(a, 150, 1));
    expect_true("an empty range does nothing", n_parallel_team_run(team, 10, 10, 1, bump, a) == 0);
    expect_true("a NULL function does nothing", n_parallel_team_run(team, 0, 10, 1, NULL, a) == 0);
    expect_true("a NULL team runs on the caller", n_parallel_team_run(NULL, 0, 10, 1, bump, a) == 1);

    /* nested on the same team */
    nest.team = team;
    nest.items = inner;
    nest.count = 64;
    n_parallel_team_run(team, 0, 16, 1, nested, &nest);
    expect_true("a nested loop runs inline and does all of it", all_equal(inner, 16 * 64, 1));

    /* two threads sharing one team */
    memset(a, 0, 100000 * sizeof(int));
    share.team = team;
    share.items = b;
    if (pthread_create(&other, NULL, sharer, &share) != 0) return 1;
    for (i = 0; i < 100; i++) n_parallel_team_run(team, 0, 100000, 100, bump, a);
    pthread_join(other, NULL);
    expect_true("two threads sharing a team both finish right", all_equal(a, 100000, 100) && all_equal(b, 100000, 100));

    /* a team of one starts no thread */
    solo = n_parallel_team_new(1);
    memset(a, 0, 100000 * sizeof(int));
    expect_true("a team of one runs as one slice", solo && n_parallel_team_run(solo, 0, 100000, 1, bump, a) == 1);
    expect_true("and does all of it", all_equal(a, 100000, 1));

    n_parallel_team_free(&solo);
    n_parallel_team_free(&team);
    expect_true("free sets the pointer to NULL", team == NULL);
    n_parallel_team_free(&team);

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