J
Jonathan Burd
Greetings everyone,
Here is a random string generator I wrote for an application
and I'm wondering about the thread-safety of this function.
I was told using static and global variables cause
potential problems for thread-safety. So far, I'm only confused.
I need a proper explanation for the concept so I can understand how
to write thread-safe functions in the future.
My apologies for posting a long routine.
#include <stdlib.h>
#include <time.h>
/* ---( PRIVATE )--- */
#define RANDSTR_MIN 32
#define RANDSTR_MAX 126
#define RANDSTR_RANGE ((RANDSTR_MAX + 1) - RANDSTR_MIN) + RANDSTR_MIN
char *
garbage (
char * buf, /* pointer to the buffer that will contain the garbage */
size_t count, /* including the last null character. */
const char * chrs /* character range used */
)
{
char * eosbuf = buf;
const char * eoschrs = NULL;
time_t timeval;
/* static & 0 IMPORTANT! Thread-safe? */
static unsigned int seed = 0;
/* (A)
* If the seed is 0 (not created yet), we generate a seed.
*/
if (seed == 0)
{
timeval = time((time_t*)NULL);
/*
* check if time is available on system
*/
if (timeval == (time_t)-1)
return (NULL);
seed = (unsigned) timeval;
/*
* Seed the random number generation algo, so we can call rand()
*/
srand (seed);
}
/* (B)
* if chrs is an empty string, choose our own range
* of characters from ASCII 32 to ASCII 126
*/
if (NULL == chrs || '\0' == *chrs)
{
/* generate only the required number of characters */
while (count-- > 1)
*eosbuf++ = (char) (rand () % RANDSTR_RANGE);
}
/* we are using a user-specified range. */
else
{
eoschrs = chrs;
/* get a pointer to point to the last character '\0' of the range.
*/
while (*eoschrs)
++eoschrs;
/* generate the random string. MAX == length of range. */
while (count-- > 1)
*eosbuf++ = *(chrs + (rand () % (size_t)(eoschrs - chrs)));
}
/* (C)
* Important: terminate the string!
*/
*eosbuf = (char) '\0';
/* (D)
* Return pointer to the buffer.
*/
return (buf);
}
Sample Usage:
=============
char buf[11]; /* 10 chars + 1 '\0' */
garbage (
buf,
sizeof (buf),
"0aA1bB2cC3dD4eE5fF6gG7hH8iI9jJk9Kl8Lm7Mn6No5Op4Pq3Qr2Rs1StT0uVvWwXxYyZz"
);
puts (buf);
Regards,
Jonathan.
Here is a random string generator I wrote for an application
and I'm wondering about the thread-safety of this function.
I was told using static and global variables cause
potential problems for thread-safety. So far, I'm only confused.
I need a proper explanation for the concept so I can understand how
to write thread-safe functions in the future.
My apologies for posting a long routine.
#include <stdlib.h>
#include <time.h>
/* ---( PRIVATE )--- */
#define RANDSTR_MIN 32
#define RANDSTR_MAX 126
#define RANDSTR_RANGE ((RANDSTR_MAX + 1) - RANDSTR_MIN) + RANDSTR_MIN
char *
garbage (
char * buf, /* pointer to the buffer that will contain the garbage */
size_t count, /* including the last null character. */
const char * chrs /* character range used */
)
{
char * eosbuf = buf;
const char * eoschrs = NULL;
time_t timeval;
/* static & 0 IMPORTANT! Thread-safe? */
static unsigned int seed = 0;
/* (A)
* If the seed is 0 (not created yet), we generate a seed.
*/
if (seed == 0)
{
timeval = time((time_t*)NULL);
/*
* check if time is available on system
*/
if (timeval == (time_t)-1)
return (NULL);
seed = (unsigned) timeval;
/*
* Seed the random number generation algo, so we can call rand()
*/
srand (seed);
}
/* (B)
* if chrs is an empty string, choose our own range
* of characters from ASCII 32 to ASCII 126
*/
if (NULL == chrs || '\0' == *chrs)
{
/* generate only the required number of characters */
while (count-- > 1)
*eosbuf++ = (char) (rand () % RANDSTR_RANGE);
}
/* we are using a user-specified range. */
else
{
eoschrs = chrs;
/* get a pointer to point to the last character '\0' of the range.
*/
while (*eoschrs)
++eoschrs;
/* generate the random string. MAX == length of range. */
while (count-- > 1)
*eosbuf++ = *(chrs + (rand () % (size_t)(eoschrs - chrs)));
}
/* (C)
* Important: terminate the string!
*/
*eosbuf = (char) '\0';
/* (D)
* Return pointer to the buffer.
*/
return (buf);
}
Sample Usage:
=============
char buf[11]; /* 10 chars + 1 '\0' */
garbage (
buf,
sizeof (buf),
"0aA1bB2cC3dD4eE5fF6gG7hH8iI9jJk9Kl8Lm7Mn6No5Op4Pq3Qr2Rs1StT0uVvWwXxYyZz"
);
puts (buf);
Regards,
Jonathan.