forked from lda/telodendria
Make RandState thread-specific.
This commit is contained in:
parent
609890654e
commit
c1c57fd4cf
1 changed files with 25 additions and 10 deletions
35
src/Rand.c
35
src/Rand.c
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <Int.h>
|
#include <Int.h>
|
||||||
#include <Util.h>
|
#include <Util.h>
|
||||||
|
#include <Memory.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
@ -97,6 +98,12 @@ RandGenerate(RandState * state)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
RandDestructor(void *p)
|
||||||
|
{
|
||||||
|
Free(p);
|
||||||
|
}
|
||||||
|
|
||||||
/* Generate random numbers using rejection sampling. The basic idea is
|
/* Generate random numbers using rejection sampling. The basic idea is
|
||||||
* to "reroll" if a number happens to be outside the range. However
|
* to "reroll" if a number happens to be outside the range. However
|
||||||
* this could be extremely inefficient.
|
* this could be extremely inefficient.
|
||||||
|
@ -112,23 +119,33 @@ RandGenerate(RandState * state)
|
||||||
void
|
void
|
||||||
RandIntN(int *buf, size_t size, unsigned int max)
|
RandIntN(int *buf, size_t size, unsigned int max)
|
||||||
{
|
{
|
||||||
static pthread_mutex_t stateLock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_key_t stateKey;
|
||||||
static UInt32 seed = 0;
|
static int createdKey = 0;
|
||||||
static RandState state;
|
|
||||||
|
|
||||||
/* Limit the range to banish all previously biased results */
|
/* Limit the range to banish all previously biased results */
|
||||||
const int allowed = RAND_MAX - RAND_MAX % max;
|
const int allowed = RAND_MAX - RAND_MAX % max;
|
||||||
|
|
||||||
|
RandState *state;
|
||||||
int tmp;
|
int tmp;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
pthread_mutex_lock(&stateLock);
|
if (!createdKey)
|
||||||
|
{
|
||||||
|
pthread_key_create(&stateKey, RandDestructor);
|
||||||
|
createdKey = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!seed)
|
state = pthread_getspecific(stateKey);
|
||||||
|
|
||||||
|
if (!state)
|
||||||
{
|
{
|
||||||
/* Generate a seed from the system time, PID, and TID */
|
/* Generate a seed from the system time, PID, and TID */
|
||||||
seed = UtilServerTs() ^ getpid() ^ (unsigned long) pthread_self();
|
UInt32 seed = UtilServerTs() ^ getpid() ^ (unsigned long) pthread_self();
|
||||||
RandSeed(&state, seed);
|
|
||||||
|
state = Malloc(sizeof(RandState));
|
||||||
|
RandSeed(state, seed);
|
||||||
|
|
||||||
|
pthread_setspecific(stateKey, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate {size} random numbers. */
|
/* Generate {size} random numbers. */
|
||||||
|
@ -137,13 +154,11 @@ RandIntN(int *buf, size_t size, unsigned int max)
|
||||||
/* Most of the time, this will take about 1 loop */
|
/* Most of the time, this will take about 1 loop */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
tmp = RandGenerate(&state);
|
tmp = RandGenerate(state);
|
||||||
} while (tmp > allowed);
|
} while (tmp > allowed);
|
||||||
|
|
||||||
buf[i] = tmp % max;
|
buf[i] = tmp % max;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&stateLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate just 1 random number */
|
/* Generate just 1 random number */
|
||||||
|
|
Loading…
Reference in a new issue