qt_loop_balance(3)
π qt_loop_balance(3) π
okay bestie, so this is a page from libqthread, and it's all about qt_loop_balance β well, technically the function it documents is qt_loopaccum_balance, and the way that discrepancy just exists? iconic. anyway. grab a boba, we're doing threaded loops π§
β¨ NAME β¨
qt_loopaccum_balance β a slightly intelligent implementation of a threaded loop that returns values π
like, "slightly intelligent" is literally what the page says and honestly? relatable.
π¦ SYNOPSIS π¦
#include <qthread/qloop.h>
void
qt_loopaccum_balance (const size_t start, const size_t stop,
const size_t size, void *out,
const qt_loopr_f func, void *argptr,
const qt_accum_f acc);
πΈ DESCRIPTION πΈ
so this function is a simple C implementation of a threaded accumulating loop. here's the tea though: instead of you picking a pre-set number of qthreads, the number of qthreads it makes depends directly on how many shepherds are available. no cap. π
and the whole point of the accumulation vibe is that you can use it to collect values from multiple threads. like, say you've got a running tally of outputs, or you absolutely must keep the maximum return value β this is how you do it. main character collection energy β¨
you can think of these functions as akin to (but NOT exactly replicating) this code:
unsigned int i;
for (i = start; i < stop; i ++) {
func (NULL, argptr, ret);
acc (tmp, ret);
}
one qthread gets spawned for each shepherd. the set of values of i (the iterations) gets divided evenly among the shepherds, and each qthread gets handed its own little set of iterations to perform. teamwork makes the dream work π«Ά
now, the func argument must be a function pointer with a qt_loopr_f prototype. and bestie, hear me: this is NOT the same as qt_loop_f functions, because it has that extra ret argument. its basic code structure is expected to look like this:
void func (const size_t startat,
const size_t stopat, void *argptr, void *ret)
{
for (unsigned int i = startat; i < stopat; i++) {
/* do work */
}
}
the arguments startat and stopat are determined by the library, and they tell the function what range of i values (iterations) it's responsible for. also: qt_loop_balance() will not return until all of the qthreads it spawned have exited. it waits. it's loyal. π
the acc argument must be a function pointer with a qt_accum_f prototype, and that prototype looks like this:
void acc (void *a, void *b);
the accumulating value lives in the memory pointed to by the a argument, and a new value comes in via the b argument. π
β οΈ okay important: when there's only a single shepherd, this function is never called, because the entire set of iterations gets handed to one single instance offuncto perform. so because of that β and because there's no guarantee about how the iterations will be divided βfuncis expected to perform essentially the same accumulation operation thataccdoes. also there's no guarantee about what order things will be accumulated in, so the operation needs to be commutative if you want every run of the program to return the same result. fr fr. π
the result of the accumulations (acc), if any, of the output (ret) of func gets stored in the memory pointed to by out. that memory is assumed to be at least size bytes, and size bytes will be used for storage of all ret arguments to func calls.
π EXAMPLE π
okay so since all of that is a bit complicated, a simple example is genuinely useful. this example is the qt_double_sum() function in the library; for simplicity's sake, the checkfeb option has been removed from this example. and this function is extremely simple:
double qt_double_sum (double *array,
size_t length)
{
double ret;
qt_loopaccum_balance (0, length, sizeof(double),
&ret, qtds_worker, array,
qtds_acc);
return ret;
}
there are two function arguments to the qt_loopaccum_balance() call: qtds_worker (as the func argument) and qtds_acc (as the acc, or "accumulator", argument). and qtds_acc is extremely simple:
static void qtds_acc (void *a, void *b)
{
*(double*)a += *(double*)b;
}
and the qtds_worker function does the real work of adding up the numbers π₯
static void qtds_worker (const size_t startat,
const size_t stopat, void *array, void *ret)
{
size_t i;
double sum = (double *)array[startat];
for (i = startat + 1; i < stopat; i++) {
sum += (double *)array[i];
}
*(double *)ret = sum;
}
π SEE ALSO π
and that's the whole page, bestie, you ate it π
β¨ this was libqthread, dated APRIL 2011, and the page is qt_loop_balance(3). go forth and accumulate commutatively, ily ππ
π¦ where this page comes from
- fedora 43: qthreads-devel 1.22^20251007gitcedb1fc-1.fc43 Β· BSD-3-Clause AND MIT AND dtoa
- fedora 44: qthreads-devel 1.22^20251007gitcedb1fc-2.fc44 Β· BSD-3-Clause AND MIT AND dtoa
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms