Skip to content

Instantly share code, notes, and snippets.

@carc1n0gen
Last active July 12, 2019 14:11
Show Gist options
  • Save carc1n0gen/1c3fe2fa5f1312993e1d to your computer and use it in GitHub Desktop.
Save carc1n0gen/1c3fe2fa5f1312993e1d to your computer and use it in GitHub Desktop.
Thread safe random numbers in c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <threads.h>
//#define NUM_THREADS 7
// Thread safe random numbers by tempering the upper 32 bits
// of a 64 bit int. The calculations are based on a seed.
//
// Create a single seed per thread and use that for every call
// lcg64_temper.
//
// credit: http://stackoverflow.com/a/19083740/2635342
static int32_t temper(int32_t x)
{
x ^= x>>11;
x ^= x<<7 & 0x9D2C5680;
x ^= x<<15 & 0xEFC60000;
x ^= x>>18;
return x;
}
int32_t lcg64_temper(uint64_t *seed)
{
*seed = 6364136223846793005ULL * *seed + 1;
return temper(*seed >> 32);
}
int threadFunction(void* data)
{
int32_t id = *(int32_t*)data;
printf("%d-th thread up\n", id);
uint64_t threadSeed = time(NULL) ^ id;
int32_t n = lcg64_temper(&threadSeed) % 20 + 1;
thrd_sleep(&(struct timespec){ .tv_sec = n }, NULL); // Sleep for a random number of seconds.
printf("%d-th thread done\n", id);
return 0;
}
int main(void)
{
const size_t NUM_THREADS = 7;
int32_t threadData[NUM_THREADS];
thrd_t threads[NUM_THREADS];
// Initialize data for each thread.
for (size_t i = 0; i < NUM_THREADS; ++i)
{
threadData[i] = i;
}
// Create the threads.
for (size_t i = 0; i < NUM_THREADS; ++i)
{
if (thrd_create(threads+i, threadFunction, threadData+i) != thrd_success)
{
printf("%zu-th thread create error\n", i);
return 1;
}
}
// Wait for all threads to complete.
for (size_t i = 0; i < NUM_THREADS; ++i)
thrd_join(threads[i], NULL);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment