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

#define NUM_THREADS 4
#define BASE_SEED 12345

// Συνάρτηση που εκτελείται από κάθε νήμα
void *generate_random_numbers(void *arg) {
    int thread_id = *(int *)arg;

    // Κάθε νήμα πρέπει να έχει τη δική του μεταβλητή κατάστασης/σπόρου
    // για να μην γράφει το ένα πάνω στο άλλο.
    // Συνδυάζουμε έναν βασικό σπόρο με το ID του νήματος (thread ID) για διαφορετικές ακολουθίες.
    unsigned int my_seed = BASE_SEED + thread_id;

    for (int i = 0; i < 3; i++) {
        // Η rand_r() είναι thread-safe γιατί χρησιμοποιεί τον δείκτη που παρέχεται
        // για τη διατήρηση της κατάστασης αντί για μια κρυφή καθολική μεταβλητή
        int random_val = rand_r(&my_seed);
        printf("Νήμα %d: παρήγαγε τον αριθμό: %d\n", thread_id, random_val);
        sleep(1);
    }

    pthread_exit(NULL); // Τερματισμός νήματος
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    printf("Έναρξη παραγωγής τυχαίων αριθμών (thread-safe)...\n");

    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        // Δημιουργία νημάτων περνώντας το μοναδικό ID ως παράμετρο.
        int rc = pthread_create(&threads[i], NULL, generate_random_numbers, &thread_ids[i]);
        
        if (rc) {
            printf("ΣΦΑΛΜΑ: κωδικός επιστροφής της pthread_create(): %d\n", rc);
            exit(-1);
        }
    }

    // Αναμονή για τον τερματισμό όλων των νημάτων.
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("Όλα τα νήματα ολοκληρώθηκαν επιτυχώς.\n");
    return 0;
}
