Labs

Concurrency make things hard to know if it works. You execute it once, it works, and 1/4 of the time it doesn't... It's pretty useful to be able to run the program 100 times without clicking 100 times on a button...

Run the target in loop - xtimes

I created a small program in Rust called xtimes that allow you to run a program X times and easily see the different possible outputs if there is a limited set of ordering possibilities.

Considering this function ran by 3 threads, what are the possible outputs ?

void task(int tid) {
    string number = to_string(tid) + " ";
    cout << number << flush;
}

Instead of guessing, let's run the program 100 times to see the result

> xtimes 100 ./build/exo
Progress preview [1;100]: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 
Results
 2 times 2 1 0
 9 times 2 0 1
29 times 0 2 1
10 times 1 2 0
13 times 1 0 2
37 times 0 1 2

Ran 100 times './build/exo', found 6 unique outputs

We have found the 6 possible outputs, because there is combinatory possibilities to order the number 1, 2 and 3. We might not obtain all possibilities on larger arrangements set, but this can help us.

When you have a dependency graph of several tasks running partly parallel and serial, this can be interesting to easily test our assumptions of the possible outputs.

How to install xtimes ?

On Fedora and Ubuntu, it is included in the previous setup (in lxup play pco).

Otherwise, you can install the Rust toolchain via rustup and then run this command.

cargo install --git https://codeberg.org/samuelroland/productivity xtimes

Run the target in loop - for loop in your shell

xtimes is a good option, except when the output are several lines long and there is a lot more that a dozen of different possible outputs. You can run your target inside a loop from your shell syntax. Make sure to skip the build step (except the first time) to speed it up.

If you have very long outputs and you want to know if a specific word is printed (such as going into a specific part of the code where you added a cout << "error" << endl, you can filter the output with grep...

To run and compile first, just run r once and then call cmr (cmake run) to skip the build step.

Fish example

for i in (seq 1 100)
  cmr | grep error
end

Bash example

for i in $(seq 1 10); do
  cmr | grep error
done

See the help of cmr by typing cmr -h if you have several targets or another specific need, such as passing down arguments.

Generate scratch projects to test things quickly

With the help of scr, you can easily create a hello world program with some starting code for PCO. As this is a cmake project, it can be run with r. Here is a demo.

See details of the demo
> scr pco
Creating scratch project for pco inside scratch-pco-2025-09-22-033517
scratch-pco-2025-09-22-033517> cat main.cpp 
#include <iostream>
#include <pcosynchro/pcomutex.h>
#include <pcosynchro/pcosemaphore.h>
#include <pcosynchro/pcothread.h>

using namespace std;

void task(int tid) {
    cout << "Thread " << tid << endl;
}

const int NB_THREADS = 4;

int main(void) {
    PcoThread *threads[NB_THREADS];
    for (int i = 0; i < NB_THREADS; i++) {
        threads[i] = new PcoThread(task, i);
    }
    for (int i = 0; i < NB_THREADS; i++) {
        threads[i]->join();
        delete threads[i];
    }
    return EXIT_SUCCESS;
}
> r
Building via cmake
...
Running ./build/exo 
Thread 1
Thread 3
Thread 0
Thread 2

MD5 generation for lab with MD5 cracker

Here is a quick function that can help you to generate MD5 hash without looking online...

Details

Bash function (simplified version)

function md5() {
  echo "The MD5 hash of litteral text '$@'"
  echo -n "$@" | md5sum
}

Fish function

## Shortcut to easily hash a value in MD5
function md5
    set -l out (echo -n "$argv" | md5sum)
    set -l hash (string sub -l 32 "$out")
    echo The MD5 hash of litteral text "'$argv'" is: $hash
end
</details>