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
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/RandomNumber.hpp"
00040 #include "blocxx/Assertion.hpp"
00041 #include "blocxx/ThreadOnce.hpp"
00042 #include "blocxx/Mutex.hpp"
00043 #include "blocxx/MutexLock.hpp"
00044 #include <fstream>
00045 #include <sys/types.h>
00046
00047 #ifdef BLOCXX_HAVE_UNISTD_H
00048 #include <unistd.h>
00049 #endif
00050
00051 #ifdef BLOCXX_HAVE_SYS_TIME_H
00052 #include <sys/time.h>
00053 #endif
00054
00055 #include <stdlib.h>
00056 #include <time.h>
00057
00058 namespace BLOCXX_NAMESPACE
00059 {
00060
00062 namespace
00063 {
00064 OnceFlag guard;
00065 unsigned int seed = 0;
00066 }
00067
00069 RandomNumber::RandomNumber(Int32 lowVal, Int32 highVal)
00070 : m_lowVal(lowVal), m_highVal(highVal)
00071 {
00072 if (lowVal > highVal)
00073 {
00074 m_lowVal = highVal;
00075 m_highVal = lowVal;
00076 }
00077 callOnce(guard, &initRandomness);
00078 }
00079
00081 void
00082 RandomNumber::initRandomness()
00083 {
00084 #ifdef BLOCXX_WIN32
00085 time_t timeval = ::time(NULL);
00086 seed = timeval;
00087 #else
00088
00089 struct timeval tv;
00090 gettimeofday(&tv, 0);
00091
00092 std::ifstream infile("/dev/urandom", std::ios::in);
00093 if (!infile)
00094 {
00095 infile.open("/dev/random", std::ios::in);
00096 }
00097
00098
00099 unsigned int dev_rand_input;
00100 if (infile)
00101 {
00102 infile.read(reinterpret_cast<char*>(&dev_rand_input), sizeof(dev_rand_input));
00103 infile.close();
00104 }
00105
00106 seed = dev_rand_input ^ (getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec;
00107 #endif
00108 #ifdef BLOCXX_HAVE_SRANDOM
00109 srandom(seed);
00110 #else
00111 srand(seed);
00112 #endif
00113 }
00114
00116 void
00117 RandomNumber::saveRandomState()
00118 {
00119
00120
00121 }
00122
00123 namespace
00124 {
00125 Mutex g_guard;
00126 }
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