rng.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef EQBASE_RNG_H
00019 #define EQBASE_RNG_H
00020
00021 #include <eq/base/debug.h>
00022 #include <eq/base/nonCopyable.h>
00023
00024 #include <fcntl.h>
00025
00026 namespace eq
00027 {
00028 namespace base
00029 {
00036 class RNG : public NonCopyable
00037 {
00038 public:
00040 RNG()
00041 {
00042 #ifdef Linux
00043 _fd = ::open( "/dev/urandom", O_RDONLY );
00044 EQASSERT( _fd != -1 );
00045 #endif
00046 reseed();
00047 }
00048
00050 ~RNG()
00051 {
00052 #ifdef Linux
00053 if( _fd > 0 )
00054 close( _fd );
00055 #endif
00056 }
00057
00059 void reseed()
00060 {
00061 #ifdef Linux
00062
00063 #elif defined (WIN32)
00064 LARGE_INTEGER seed;
00065 QueryPerformanceCounter( &seed );
00066 srand( seed.LowPart );
00067 #else // Darwin
00068 srandomdev();
00069 #endif
00070 }
00071
00073 template< typename T >
00074 T get()
00075 {
00076 T value;
00077 #ifdef Linux
00078 int read = ::read( _fd, &value, sizeof( T ));
00079 EQASSERT( read == sizeof( T ));
00080 if( read != sizeof( T ))
00081 {
00082 EQERROR << "random number generator not working" << std::endl;
00083 return 0;
00084 }
00085
00086 #elif defined (WIN32)
00087
00088 EQASSERTINFO( RAND_MAX >= 32767, RAND_MAX );
00089
00090 uint8_t* bytes = reinterpret_cast< uint8_t* >( &value );
00091 for( size_t i=0; i<sizeof( T ); ++i )
00092 bytes[i] = ( rand() & 255 );
00093 #else // Darwin
00094 uint8_t* bytes = reinterpret_cast< uint8_t* >( &value );
00095 for( size_t i=0; i<sizeof( T ); ++i )
00096 bytes[i] = ( random() & 255 );
00097 #endif
00098 return value;
00099 }
00100
00101 private:
00102 #ifdef Linux
00103 int _fd;
00104 #endif
00105 };
00106 }
00107 }
00108 #endif // EQBASE_RNG_H