00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039 #include "blocxx/BLOCXX_config.h"
00040 #include "blocxx/RandomNumber.hpp"
00041 #include "blocxx/Assertion.hpp"
00042 #include "blocxx/ThreadOnce.hpp"
00043 #include "blocxx/Mutex.hpp"
00044 #include "blocxx/MutexLock.hpp"
00045 #include "blocxx/GlobalMutex.hpp"
00046 #include <fstream>
00047 #include <sys/types.h>
00048
00049 #ifdef BLOCXX_HAVE_UNISTD_H
00050 #include <unistd.h>
00051 #endif
00052
00053 #ifdef BLOCXX_HAVE_SYS_TIME_H
00054 #include <sys/time.h>
00055 #endif
00056
00057 #include <stdlib.h>
00058 #include <time.h>
00059
00060 namespace BLOCXX_NAMESPACE
00061 {
00062
00064 namespace
00065 {
00066 OnceFlag guard = BLOCXX_ONCE_INIT;
00067 unsigned int seed = 0;
00068 }
00069
00071 RandomNumber::RandomNumber(Int32 lowVal, Int32 highVal)
00072 : m_lowVal(lowVal), m_highVal(highVal)
00073 {
00074 if (lowVal > highVal)
00075 {
00076 m_lowVal = highVal;
00077 m_highVal = lowVal;
00078 }
00079 callOnce(guard, &initRandomness);
00080 }
00081
00083 void
00084 RandomNumber::initRandomness()
00085 {
00086 #ifdef BLOCXX_WIN32
00087 time_t timeval = ::time(NULL);
00088 seed = timeval;
00089 #else
00090
00091 struct timeval tv;
00092 gettimeofday(&tv, 0);
00093
00094 std::ifstream infile("/dev/urandom", std::ios::in);
00095 if (!infile)
00096 {
00097 infile.open("/dev/random", std::ios::in);
00098 }
00099
00100
00101 unsigned int dev_rand_input;
00102 if (infile)
00103 {
00104 infile.read(reinterpret_cast<char*>(&dev_rand_input), sizeof(dev_rand_input));
00105 infile.close();
00106 }
00107
00108 seed = dev_rand_input ^ (getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec;
00109 #endif
00110 #ifdef BLOCXX_HAVE_SRANDOM
00111 srandom(seed);
00112 #else
00113 srand(seed);
00114 #endif
00115 }
00116
00118 void
00119 RandomNumber::saveRandomState()
00120 {
00121
00122 }
00123
00124 namespace
00125 {
00126 GlobalMutex g_guard = BLOCXX_GLOBAL_MUTEX_INIT();
00127 }
00129 Int32
00130 RandomNumber::getNextNumber()
00131 {
00132 MutexLock lock(g_guard);
00133 #ifdef BLOCXX_HAVE_RANDOM
00134 return m_lowVal + (random() % (m_highVal - m_lowVal + 1));
00135 #else
00136 return m_lowVal + (rand() % (m_highVal - m_lowVal + 1));
00137 #endif
00138 }
00139
00140 }
00141