From 7c9ff7c8ff118a1d3cdd1cae5ea9b4bbfac8cefb Mon Sep 17 00:00:00 2001 From: chasonr Date: Tue, 25 Feb 2014 00:06:31 -0500 Subject: Implement default Random instance. Previously, the default random number generator was implemented using static storage. This storage is common to all instances of mruby in a process, and use of the default random number generator in one instance will perturb the default random number generator in other instances. It is also not thread safe. With this change, the default random number generator is defined as Random::DEFAULT, as it is in CRuby. --- mrbgems/mruby-random/src/mt19937ar.c | 4 ++ mrbgems/mruby-random/src/random.c | 99 ++++++++---------------------------- 2 files changed, 24 insertions(+), 79 deletions(-) diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c index 2c22b23ad..b237af56d 100644 --- a/mrbgems/mruby-random/src/mt19937ar.c +++ b/mrbgems/mruby-random/src/mt19937ar.c @@ -14,8 +14,10 @@ #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ +#if 0 /* dead_code */ static unsigned long mt[N]; /* the array for the state vector */ static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ +#endif /* dead_code */ void mrb_random_init_genrand(mt_state *t, unsigned long s) { @@ -74,6 +76,7 @@ double mrb_random_genrand_real1(mt_state *t) /* divided by 2^32-1 */ } +#if 0 /* dead_code */ /* initializes mt[N] with a seed */ void init_genrand(unsigned long s) { @@ -191,3 +194,4 @@ double genrand_res53(void) return(a*67108864.0+b)*(1.0/9007199254740992.0); } /* These real versions are due to Isaku Wada, 2002/01/09 added */ +#endif /* dead_code */ diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index ac8f24a18..a708923d3 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -20,51 +20,9 @@ static const struct mrb_data_type mt_state_type = { MT_STATE_KEY, mrb_free, }; -static void mt_g_srand(unsigned long seed) -{ - init_genrand(seed); -} +static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self); +static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self); -static unsigned long mt_g_rand(void) -{ - return genrand_int32(); -} - -static double mt_g_rand_real(void) -{ - return genrand_real1(); -} - -static mrb_value -mrb_random_mt_g_srand(mrb_state *mrb, mrb_value seed) -{ - if (mrb_nil_p(seed)) { - seed = mrb_fixnum_value(time(NULL) + mt_g_rand()); - if (mrb_fixnum(seed) < 0) { - seed = mrb_fixnum_value( 0 - mrb_fixnum(seed)); - } - } - - mt_g_srand((unsigned) mrb_fixnum(seed)); - - return seed; -} - -static mrb_value -mrb_random_mt_g_rand(mrb_state *mrb, mrb_value max) -{ - mrb_value value; - - if (mrb_fixnum(max) == 0) { - value = mrb_float_value(mrb, mt_g_rand_real()); - } - else { - value = mrb_fixnum_value(mt_g_rand() % mrb_fixnum(max)); - } - - return value; -} - static void mt_srand(mt_state *t, unsigned long seed) { @@ -133,38 +91,22 @@ get_opt(mrb_state* mrb) return arg; } -static void -mrb_random_g_rand_seed(mrb_state *mrb) -{ - mrb_value seed; - - seed = mrb_gv_get(mrb, mrb_intern_lit(mrb, GLOBAL_RAND_SEED_KEY)); - if (mrb_nil_p(seed)) { - mrb_random_mt_g_srand(mrb, mrb_nil_value()); - } -} - static mrb_value mrb_random_g_rand(mrb_state *mrb, mrb_value self) { - mrb_value max; - - max = get_opt(mrb); - mrb_random_g_rand_seed(mrb); - return mrb_random_mt_g_rand(mrb, max); + mrb_value random = mrb_const_get(mrb, + mrb_obj_value(mrb_class_get(mrb, "Random")), + mrb_intern_lit(mrb, "DEFAULT")); + return mrb_random_rand(mrb, random); } static mrb_value mrb_random_g_srand(mrb_state *mrb, mrb_value self) { - mrb_value seed; - mrb_value old_seed; - - seed = get_opt(mrb); - seed = mrb_random_mt_g_srand(mrb, seed); - old_seed = mrb_gv_get(mrb, mrb_intern_lit(mrb, GLOBAL_RAND_SEED_KEY)); - mrb_gv_set(mrb, mrb_intern_lit(mrb, GLOBAL_RAND_SEED_KEY), seed); - return old_seed; + mrb_value random = mrb_const_get(mrb, + mrb_obj_value(mrb_class_get(mrb, "Random")), + mrb_intern_lit(mrb, "DEFAULT")); + return mrb_random_srand(mrb, random); } static mrb_value @@ -258,12 +200,13 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) if (RARRAY_LEN(ary) > 1) { mrb_get_args(mrb, "|d", &random, &mt_state_type); - if (random) { - mrb_random_rand_seed(mrb, random); - } - else { - mrb_random_g_rand_seed(mrb); + if (random == NULL) { + mrb_value random_val = mrb_const_get(mrb, + mrb_obj_value(mrb_class_get(mrb, "Random")), + mrb_intern_lit(mrb, "DEFAULT")); + random = (mt_state *)DATA_PTR(random_val); } + mrb_random_rand_seed(mrb, random); mrb_ary_modify(mrb, mrb_ary_ptr(ary)); @@ -271,12 +214,7 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) mrb_int j; mrb_value tmp; - if (random) { - j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); - } - else { - j = mrb_fixnum(mrb_random_mt_g_rand(mrb, mrb_fixnum_value(RARRAY_LEN(ary)))); - } + j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); tmp = RARRAY_PTR(ary)[i]; RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j]; @@ -322,6 +260,9 @@ void mrb_mruby_random_gem_init(mrb_state *mrb) mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1)); mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_OPT(1)); + + mrb_const_set(mrb, mrb_obj_value(random), mrb_intern_lit(mrb, "DEFAULT"), + mrb_obj_new(mrb, random, 0, NULL)); } void mrb_mruby_random_gem_final(mrb_state *mrb) -- cgit v1.2.3 From 985e4892cfcad52168af55b3b2ebc2c7e6a3b414 Mon Sep 17 00:00:00 2001 From: cubicdaiya Date: Tue, 25 Feb 2014 15:03:35 +0900 Subject: small-optimization for mrb_time_zone Using mrb_str_new instead of mrb_str_new_cstr --- mrbgems/mruby-time/src/time.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 8bea2cb5b..7f513624f 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -93,11 +93,16 @@ enum mrb_timezone { MRB_TIMEZONE_LAST = 3 }; -static const char *timezone_names[] = { - "none", - "UTC", - "LOCAL", - NULL +typedef struct mrb_timezone_name { + const char *name; + size_t len; +} mrb_timezone_name; + +static mrb_timezone_name timezone_names[] = { + { "none", sizeof("none") - 1 }, + { "UTC", sizeof("UTC") - 1 }, + { "LOCAL", sizeof("LOCAL") - 1 }, + { NULL, 0 } }; static const char *mon_names[] = { @@ -401,7 +406,9 @@ mrb_time_zone(mrb_state *mrb, mrb_value self) tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); - return mrb_str_new_cstr(mrb, timezone_names[tm->timezone]); + return mrb_str_new(mrb, + timezone_names[tm->timezone].name, + timezone_names[tm->timezone].len); } /* 15.2.19.7.4 */ -- cgit v1.2.3 From 96c24b0a37d55dad37a80f408c466dfb2285faaf Mon Sep 17 00:00:00 2001 From: cubicdaiya Date: Tue, 25 Feb 2014 15:24:02 +0900 Subject: small-optimization2 for mrb_time_zone mrb_str_new_static is more efficient than mrb_str_new in this case. --- mrbgems/mruby-time/src/time.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 7f513624f..a13af790b 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -406,9 +406,9 @@ mrb_time_zone(mrb_state *mrb, mrb_value self) tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); - return mrb_str_new(mrb, - timezone_names[tm->timezone].name, - timezone_names[tm->timezone].len); + return mrb_str_new_static(mrb, + timezone_names[tm->timezone].name, + timezone_names[tm->timezone].len); } /* 15.2.19.7.4 */ -- cgit v1.2.3