Revision: 2826 http://trac.macosforge.org/projects/ruby/changeset/2826 Author: lsansonetti@apple.com Date: 2009-10-15 18:37:01 -0700 (Thu, 15 Oct 2009) Log Message: ----------- re-implemented #rand and #srand to use random(3) and srandom(3), faster and thread-safe (patch contributed by Thibault Martin-Lagardette) Modified Paths: -------------- MacRuby/trunk/bignum.c MacRuby/trunk/include/ruby/intern.h MacRuby/trunk/numeric.c MacRuby/trunk/random.c MacRuby/trunk/vm.cpp MacRuby/trunk/vm.h Modified: MacRuby/trunk/bignum.c =================================================================== --- MacRuby/trunk/bignum.c 2009-10-16 01:30:42 UTC (rev 2825) +++ MacRuby/trunk/bignum.c 2009-10-16 01:37:01 UTC (rev 2826) @@ -1377,8 +1377,8 @@ * Unary minus (returns a new Bignum whose value is 0-big) */ -static VALUE -rb_big_uminus(VALUE x, SEL sel) +VALUE +rb_big_uminus(VALUE x) { VALUE z = rb_big_clone(x); @@ -1387,6 +1387,12 @@ return bignorm(z); } +static VALUE +rb_big_uminus_imp(VALUE x, SEL sel) +{ + return rb_big_uminus(x); +} + /* * call-seq: * ~big => integer @@ -2833,7 +2839,7 @@ rb_objc_define_method(rb_cBignum, "to_s", rb_big_to_s, -1); rb_objc_define_method(rb_cBignum, "coerce", rb_big_coerce, 1); - rb_objc_define_method(rb_cBignum, "-@", rb_big_uminus, 0); + rb_objc_define_method(rb_cBignum, "-@", rb_big_uminus_imp, 0); rb_objc_define_method(rb_cBignum, "+", rb_big_plus_imp, 1); rb_objc_define_method(rb_cBignum, "-", rb_big_minus_imp, 1); rb_objc_define_method(rb_cBignum, "*", rb_big_mul_imp, 1); Modified: MacRuby/trunk/include/ruby/intern.h =================================================================== --- MacRuby/trunk/include/ruby/intern.h 2009-10-16 01:30:42 UTC (rev 2825) +++ MacRuby/trunk/include/ruby/intern.h 2009-10-16 01:37:01 UTC (rev 2826) @@ -124,6 +124,7 @@ VALUE rb_big_xor(VALUE, VALUE); VALUE rb_big_lshift(VALUE, VALUE); VALUE rb_big_rshift(VALUE, VALUE); +VALUE rb_big_uminus(VALUE x); /* rational.c */ VALUE rb_rational_raw(VALUE, VALUE); #define rb_rational_raw1(x) rb_rational_raw(x, INT2FIX(1)) @@ -415,6 +416,8 @@ VALUE rb_float_new(double); VALUE rb_num2fix(VALUE); VALUE rb_fix2str(VALUE, int); +VALUE rb_fix_minus(VALUE x, VALUE y); +VALUE rb_fix_uminus(VALUE num); VALUE rb_dbl_cmp(double, double); /* object.c */ VALUE rb_send_dup(VALUE); Modified: MacRuby/trunk/numeric.c =================================================================== --- MacRuby/trunk/numeric.c 2009-10-16 01:30:42 UTC (rev 2825) +++ MacRuby/trunk/numeric.c 2009-10-16 01:37:01 UTC (rev 2826) @@ -2131,10 +2131,17 @@ * Negates <code>fix</code> (which might return a Bignum). */ +VALUE +rb_fix_uminus(VALUE num) +{ + return LONG2NUM(-FIX2LONG(num)); +} + + static VALUE fix_uminus(VALUE num, SEL sel) { - return LONG2NUM(-FIX2LONG(num)); + return rb_fix_uminus(num); } VALUE Modified: MacRuby/trunk/random.c =================================================================== --- MacRuby/trunk/random.c 2009-10-16 01:30:42 UTC (rev 2825) +++ MacRuby/trunk/random.c 2009-10-16 01:37:01 UTC (rev 2826) @@ -9,177 +9,13 @@ **********************************************************************/ -/* -This is based on trimmed version of MT19937. To get the original version, -contact <http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html>. - -The original copyright notice follows. - - A C-program for MT19937, with initialization improved 2002/2/10. - Coded by Takuji Nishimura and Makoto Matsumoto. - This is a faster version by taking Shawn Cokus's optimization, - Matthe Bellew's simplification, Isaku Wada's real version. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.keio.ac.jp/matumoto/emt.html - email: matumoto@math.keio.ac.jp -*/ - -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UMASK 0x80000000UL /* most significant w-r bits */ -#define LMASK 0x7fffffffUL /* least significant r bits */ -#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) -#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) - -static unsigned long state[N]; /* the array for the state vector */ -static int left = 1; -static int initf = 0; -static unsigned long *next; - -/* initializes state[N] with a seed */ -static void -init_genrand(unsigned long s) -{ - int j; - state[0]= s & 0xffffffffUL; - for (j=1; j<N; j++) { - state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array state[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - state[j] &= 0xffffffffUL; /* for >32 bit machines */ - } - left = 1; initf = 1; -} - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -static void -init_by_array(unsigned long init_key[], int key_length) -{ - int i, j, k; - init_genrand(19650218UL); - i=1; j=0; - k = (N>key_length ? N : key_length); - for (; k; k--) { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL)) - + init_key[j] + j; /* non linear */ - state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { state[0] = state[N-1]; i=1; } - if (j>=key_length) j=0; - } - for (k=N-1; k; k--) { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL)) - - i; /* non linear */ - state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { state[0] = state[N-1]; i=1; } - } - - state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ - left = 1; initf = 1; -} - -static void -next_state(void) -{ - unsigned long *p=state; - int j; - - /* if init_genrand() has not been called, */ - /* a default initial seed is used */ - if (initf==0) init_genrand(5489UL); - - left = N; - next = state; - - for (j=N-M+1; --j; p++) - *p = p[M] ^ TWIST(p[0], p[1]); - - for (j=M; --j; p++) - *p = p[M-N] ^ TWIST(p[0], p[1]); - - *p = p[M-N] ^ TWIST(p[0], state[0]); -} - -/* generates a random number on [0,0xffffffff]-interval */ -static unsigned long -genrand_int32(void) -{ - unsigned long y; - - if (--left == 0) next_state(); - y = *next++; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} - -/* generates a random number on [0,1) with 53-bit resolution*/ -static double -genrand_real(void) -{ - unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} -/* These real versions are due to Isaku Wada, 2002/01/09 added */ - -#undef N -#undef M - -/* These real versions are due to Isaku Wada, 2002/01/09 added */ - #include "ruby/ruby.h" #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#include <limits.h> +#include <math.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> @@ -187,129 +23,107 @@ #include <fcntl.h> #endif -unsigned long -rb_genrand_int32(void) +#include "ruby/node.h" +#include "vm.h" + + +static void +init_random(void) { - return genrand_int32(); + srandomdev(); } -double -rb_genrand_real(void) +/* + * #rand(0) needs to generate a float x, such as 0.0 <= x <= 1.0. However, + * srandom() returns a long. We want to convert that long by dividing it until + * it is <= 1.0 using its 10th power. + * For performance reasons, long_to_float_divider() returns the 10th power of + * the number, without calculating the number length and using pow(). + */ +static inline unsigned long +long_to_float_divider(long val) { - return genrand_real(); + unsigned long divider = 1; + + while (divider <= val) { + divider *= 10; + } + return divider; } -static VALUE saved_seed = INT2FIX(0); - static VALUE -rand_init(VALUE vseed) +random_number_with_limit(long limit) { - volatile VALUE seed; - VALUE old; - long len; - unsigned long *buf; + long val; - seed = rb_to_int(vseed); - switch (TYPE(seed)) { - case T_FIXNUM: - len = sizeof(VALUE); - break; - case T_BIGNUM: - len = RBIGNUM_LEN(seed) * SIZEOF_BDIGITS; - if (len == 0) - len = 4; - break; - default: - rb_raise(rb_eTypeError, "failed to convert %s into Integer", - rb_obj_classname(vseed)); + if (limit == 0) { +#if __LP64__ + val = random(); +#else + val = random() % (ULONG_MAX / 10); +#endif /* !__LP64__ */ + return DOUBLE2NUM((double)val / long_to_float_divider(val)); } - len = (len + 3) / 4; /* number of 32bit words */ - buf = ALLOC_N(unsigned long, len); /* allocate longs for init_by_array */ - memset(buf, 0, len * sizeof(long)); - if (FIXNUM_P(seed)) { - buf[0] = FIX2ULONG(seed) & 0xffffffff; -#if SIZEOF_LONG > 4 - buf[1] = FIX2ULONG(seed) >> 32; -#endif - } else { - int i, j; - for (i = RBIGNUM_LEN(seed)-1; 0 <= i; i--) { - j = i * SIZEOF_BDIGITS / 4; -#if SIZEOF_BDIGITS < 4 - buf[j] <<= SIZEOF_BDIGITS * 8; -#endif - buf[j] |= RBIGNUM_DIGITS(seed)[i]; - } + if (limit < 0) { + /* -LONG_MIN = LONG_MIN, let's avoid that */ + if (limit == LONG_MIN) { + limit += 1; + } + limit = -limit; + } + val = random() % limit; + return LONG2NUM(val); } - while (1 < len && buf[len-1] == 0) { - len--; - } - if (len <= 1) { - init_genrand(buf[0]); - } - else { - if (buf[len-1] == 1) /* remove leading-zero-guard */ - len--; - init_by_array(buf, len); - } - old = saved_seed; - saved_seed = seed; - xfree(buf); - return old; + return Qnil; } +unsigned long rb_genrand_int32(void); + static VALUE -random_seed(void) +random_number_with_bignum_limit(struct RBignum *bignum_limit) { - static int n = 0; - struct timeval tv; - int fd; - struct stat statbuf; + long nb_long_in_bignum; + long nb_loops; + struct RBignum *div_result; + struct RBignum *result; + int idx; - int seed_len; - BDIGIT *digits; - unsigned long *seed; - NEWOBJ(big, struct RBignum); - OBJSETUP(big, rb_cBignum, T_BIGNUM); + div_result = RBIGNUM(rb_big_div((VALUE)bignum_limit, LONG2NUM(LONG_MAX))); + // FIXME: Shouldn't use !, what value should I check? + if (!FIXNUM_P((VALUE)div_result)) { + rb_raise(rb_eArgError, "max is too huge"); + } - seed_len = 4 * sizeof(long); - RBIGNUM_SET_SIGN(big, 1); - rb_big_resize((VALUE)big, seed_len / SIZEOF_BDIGITS + 1); - digits = RBIGNUM_DIGITS(big); - seed = (unsigned long *)RBIGNUM_DIGITS(big); + nb_long_in_bignum = FIX2LONG((VALUE)div_result); + nb_loops = 1 + FIX2LONG(random_number_with_limit(nb_long_in_bignum)); + result = RBIGNUM(rb_int2big(0)); + for (idx = 0; idx < nb_loops; idx++) { + // This creates a bignum on each iteration... Not really good :-/ + result = RBIGNUM(rb_big_plus((VALUE)result, random_number_with_limit(LONG_MAX))); + } + return ((VALUE)result); +} - memset(digits, 0, RBIGNUM_LEN(big) * SIZEOF_BDIGITS); +unsigned long +rb_genrand_int32(void) +{ + unsigned long result; + short nb_loops; + int idx; -#ifdef S_ISCHR - if ((fd = open("/dev/urandom", O_RDONLY -#ifdef O_NONBLOCK - |O_NONBLOCK -#endif -#ifdef O_NOCTTY - |O_NOCTTY -#endif -#ifdef O_NOFOLLOW - |O_NOFOLLOW -#endif - )) >= 0) { - if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) { - read(fd, seed, seed_len); - } - close(fd); + result = 0; + nb_loops = 1 + (random() % 2); + for (idx = 0; idx < nb_loops; idx++) { + result += random(); } -#endif + return result; +} - gettimeofday(&tv, 0); - seed[0] ^= tv.tv_usec; - seed[1] ^= tv.tv_sec; - seed[2] ^= getpid() ^ (n++ << 16); - seed[3] ^= (unsigned long)&seed; - - /* set leading-zero-guard if need. */ - digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0; - - return rb_big_norm((VALUE)big); +double +rb_genrand_real(void) +{ + return NUM2DBL(random_number_with_limit(0)); } /* @@ -329,103 +143,51 @@ static VALUE rb_f_srand(VALUE obj, SEL sel, int argc, VALUE *argv) { - VALUE seed, old; + VALUE old_seed; + VALUE seed_param; + VALUE seed_int; + unsigned seed = 0; - rb_secure(4); if (argc == 0) { - seed = random_seed(); + srandomdev(); + seed = (unsigned)random(); + seed_int = UINT2NUM(seed); } else { - rb_scan_args(argc, argv, "01", &seed); + rb_scan_args(argc, argv, "01", &seed_param); + seed_int = rb_to_int(seed_param); + switch (TYPE(seed_int)) { + case T_BIGNUM: + // In case we need to keep 'seed.to_i.abs' + /* + if (RBIGNUM_NEGATIVE_P(seed_int)) { + seed_int = rb_big_uminus(seed_int); + } + */ + for (int i = 0; i < RBIGNUM_LEN(seed_int); i++) { + seed += (unsigned int)RBIGNUM_DIGITS(seed_int)[i]; + } + break ; + case T_FIXNUM: + // In case we need to keep 'seed.to_i.abs' + /* + if (FIX2LONG(seed_int) < 0) { + seed_int = rb_fix_uminus(seed_int); + } + */ + seed = (unsigned int)FIX2LONG(seed_int); + break ; + } } - old = rand_init(seed); + srandom(seed); - return old; + old_seed = rb_vm_rand_seed(); + // Ruby's behaviour is weird. It stores the 'seed.to_i' value, instead of + // the 'seed.to_i.abs' value, or just 'seed'. Which one should we use? + rb_vm_set_rand_seed(seed_int); + return old_seed; } -static unsigned long -make_mask(unsigned long x) -{ - x = x | x >> 1; - x = x | x >> 2; - x = x | x >> 4; - x = x | x >> 8; - x = x | x >> 16; -#if 4 < SIZEOF_LONG - x = x | x >> 32; -#endif - return x; -} - -static unsigned long -limited_rand(unsigned long limit) -{ - unsigned long mask = make_mask(limit); - int i; - unsigned long val; - - retry: - val = 0; - for (i = SIZEOF_LONG/4-1; 0 <= i; i--) { - if (mask >> (i * 32)) { - val |= genrand_int32() << (i * 32); - val &= mask; - if (limit < val) - goto retry; - } - } - return val; -} - -static VALUE -limited_big_rand(struct RBignum *limit) -{ - unsigned long mask, lim, rnd; - struct RBignum *val; - int i, len, boundary; - - len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4; - val = (struct RBignum *)rb_big_clone((VALUE)limit); - RBIGNUM_SET_SIGN(val, 1); -#if SIZEOF_BDIGITS == 2 -# define BIG_GET32(big,i) \ - (RBIGNUM_DIGITS(big)[(i)*2] | \ - ((i)*2+1 < RBIGNUM_LEN(big) ? \ - (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \ - 0)) -# define BIG_SET32(big,i,d) \ - ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \ - ((i)*2+1 < RBIGNUM_LEN(big) ? \ - (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \ - 0)) -#else - /* SIZEOF_BDIGITS == 4 */ -# define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[i]) -# define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[i] = (d)) -#endif - retry: - mask = 0; - boundary = 1; - for (i = len-1; 0 <= i; i--) { - lim = BIG_GET32(limit, i); - mask = mask ? 0xffffffff : make_mask(lim); - if (mask) { - rnd = genrand_int32() & mask; - if (boundary) { - if (lim < rnd) - goto retry; - if (rnd < lim) - boundary = 0; - } - } - else { - rnd = 0; - } - BIG_SET32(val, i, rnd); - } - return rb_big_norm((VALUE)val); -} - /* * call-seq: * rand(max=0) => number @@ -449,61 +211,54 @@ static VALUE rb_f_rand(VALUE obj, SEL sel, int argc, VALUE *argv) { - VALUE vmax; - long val, max; + VALUE arg_max; + long max; - rb_scan_args(argc, argv, "01", &vmax); - switch (TYPE(vmax)) { + rb_scan_args(argc, argv, "01", &arg_max); + switch (TYPE(arg_max)) { case T_FLOAT: - if (RFLOAT_VALUE(vmax) <= LONG_MAX && RFLOAT_VALUE(vmax) >= LONG_MIN) { - max = (long)RFLOAT_VALUE(vmax); + if (RFLOAT_VALUE(arg_max) <= LONG_MAX && RFLOAT_VALUE(arg_max) >= LONG_MIN) { + max = (long)RFLOAT_VALUE(arg_max); break; } - if (RFLOAT_VALUE(vmax) < 0) - vmax = rb_dbl2big(-RFLOAT_VALUE(vmax)); + if (RFLOAT_VALUE(arg_max) < 0) + arg_max = rb_dbl2big(-RFLOAT_VALUE(arg_max)); else - vmax = rb_dbl2big(RFLOAT_VALUE(vmax)); + arg_max = rb_dbl2big(RFLOAT_VALUE(arg_max)); /* fall through */ case T_BIGNUM: bignum: { - struct RBignum *limit = (struct RBignum *)vmax; + struct RBignum *limit = (struct RBignum *)arg_max; if (!RBIGNUM_SIGN(limit)) { - limit = (struct RBignum *)rb_big_clone(vmax); + limit = (struct RBignum *)rb_big_clone(arg_max); RBIGNUM_SET_SIGN(limit, 1); } limit = (struct RBignum *)rb_big_minus((VALUE)limit, INT2FIX(1)); if (FIXNUM_P((VALUE)limit)) { - if (FIX2LONG((VALUE)limit) == -1) - return DOUBLE2NUM(genrand_real()); - return LONG2NUM(limited_rand(FIX2LONG((VALUE)limit))); + max = FIX2LONG((VALUE)limit) + 1; + break; } - return limited_big_rand(limit); + return random_number_with_bignum_limit(limit); } case T_NIL: max = 0; break; default: - vmax = rb_Integer(vmax); - if (TYPE(vmax) == T_BIGNUM) goto bignum; + arg_max = rb_Integer(arg_max); + if (TYPE(arg_max) == T_BIGNUM) goto bignum; case T_FIXNUM: - max = FIX2LONG(vmax); + max = FIX2LONG(arg_max); break; } - if (max == 0) { - return DOUBLE2NUM(genrand_real()); - } - if (max < 0) max = -max; - val = limited_rand(max-1); - return LONG2NUM(val); + return random_number_with_limit(max); } void Init_Random(void) { - rand_init(random_seed()); + init_random(); rb_objc_define_module_function(rb_mKernel, "srand", rb_f_srand, -1); rb_objc_define_module_function(rb_mKernel, "rand", rb_f_rand, -1); - rb_global_variable(&saved_seed); } Modified: MacRuby/trunk/vm.cpp =================================================================== --- MacRuby/trunk/vm.cpp 2009-10-16 01:30:42 UTC (rev 2825) +++ MacRuby/trunk/vm.cpp 2009-10-16 01:37:01 UTC (rev 2826) @@ -190,6 +190,9 @@ pthread_assert(pthread_mutex_init(&gl, 0)); + // Fixnum is an immediate type, no need to retain + rand_seed = INT2FIX(0); + load_path = rb_ary_new(); rb_objc_retain((void *)load_path); @@ -920,6 +923,35 @@ } extern "C" +VALUE +rb_vm_rand_seed(void) +{ + VALUE rand_seed; + RoxorCore *core = GET_CORE(); + + core->lock(); + rand_seed = core->get_rand_seed(); + core->unlock(); + + return rand_seed; +} + +extern "C" +void +rb_vm_set_rand_seed(VALUE rand_seed) +{ + RoxorCore *core = GET_CORE(); + + core->lock(); + if (core->get_rand_seed() != rand_seed) { + GC_RELEASE(core->get_rand_seed()); + GC_RETAIN(rand_seed); + core->set_rand_seed(rand_seed); + } + core->unlock(); +} + +extern "C" bool rb_vm_abort_on_exception(void) { Modified: MacRuby/trunk/vm.h =================================================================== --- MacRuby/trunk/vm.h 2009-10-16 01:30:42 UTC (rev 2825) +++ MacRuby/trunk/vm.h 2009-10-16 01:37:01 UTC (rev 2826) @@ -259,6 +259,8 @@ void rb_vm_init_compiler(void); bool rb_vm_running(void); void rb_vm_set_running(bool flag); +VALUE rb_vm_rand_seed(void); +void rb_vm_set_rand_seed(VALUE rand_seed); bool rb_vm_parse_in_eval(void); void rb_vm_set_parse_in_eval(bool flag); VALUE rb_vm_load_path(void); @@ -551,6 +553,7 @@ pthread_mutex_t gl; VALUE loaded_features; VALUE load_path; + VALUE rand_seed; // Cache to avoid compiling the same Function twice. std::map<Function *, IMP> JITcache; @@ -603,6 +606,7 @@ ACCESSOR(running, bool); ACCESSOR(multithreaded, bool); ACCESSOR(abort_on_exception, bool); + ACCESSOR(rand_seed, VALUE); READER(loaded_features, VALUE); READER(load_path, VALUE); READER(threads, VALUE);
participants (1)
-
source_changes@macosforge.org