[ruby-dev:30037] Re: autoloading static linked extension
From:
Nobuyoshi Nakada <nobu@...>
Date:
2006-12-19 16:07:11 UTC
List:
ruby-dev #30037
なかだです。
At Tue, 19 Dec 2006 07:43:02 +0900,
Akinori MUSHA wrote in [ruby-dev:30027]:
> rb_provided() の if ブロックは括弧が抜けていますか?
すいません、抜けてるというか、直しかけだったようです。
> 1.8 については手元でテストしたいので別途ッチをお願いします。
これでどうでしょうか。
Index: eval.c
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.616.2.200
diff -U 2 -p -r1.616.2.200 eval.c
--- eval.c 9 Dec 2006 12:40:17 -0000 1.616.2.200
+++ eval.c 19 Dec 2006 15:51:06 -0000
@@ -6930,5 +6930,14 @@ static st_table *loading_tbl;
#endif
-static char *
+
+static const char *const loadable_ext[] = {
+ ".rb", DLEXT,
+#ifdef DLEXT2
+ DLEXT2,
+#endif
+ 0
+};
+
+static int
rb_feature_p(feature, ext, rb)
const char *feature, *ext;
@@ -6936,5 +6945,5 @@ rb_feature_p(feature, ext, rb)
{
VALUE v;
- char *f, *e;
+ const char *f, *e;
long i, len, elen;
@@ -6947,30 +6956,42 @@ rb_feature_p(feature, ext, rb)
elen = 0;
}
- for (i = 0; i < RARRAY(rb_features)->len; ++i) {
- v = RARRAY(rb_features)->ptr[i];
+ for (i = 0; i < RARRAY_LEN(rb_features); ++i) {
+ v = RARRAY_PTR(rb_features)[i];
f = StringValuePtr(v);
- if (strncmp(f, feature, len) != 0) continue;
+ if (RSTRING_LEN(v) < len || strncmp(f, feature, len) != 0)
+ continue;
if (!*(e = f + len)) {
if (ext) continue;
- return e;
+ return 'u';
}
if (*e != '.') continue;
if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
- return e;
+ return 's';
}
if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
- return e;
+ return 'r';
+ }
+ }
+ if (loading_tbl) {
+ e = ext;
+ if (!st_lookup(loading_tbl, (st_data_t)feature, 0)) {
+ char *buf;
+
+ if (ext) return 0;
+ buf = ALLOCA_N(char, len+8);
+ strcpy(buf, feature);
+ for (i = 0; (e = loadable_ext[i]) != 0; i++) {
+ strcpy(buf + len, loadable_ext[i]);
+ if (st_lookup(loading_tbl, (st_data_t)buf, 0)) {
+ break;
+ }
+ }
}
+ return !e ? 'u' : strcmp(e, ".rb") ? 's' : 'r';
}
return 0;
}
-static const char *const loadable_ext[] = {
- ".rb", DLEXT,
-#ifdef DLEXT2
- DLEXT2,
-#endif
- 0
-};
+static int search_required(VALUE, VALUE *, VALUE *);
int
@@ -6978,17 +6999,12 @@ rb_provided(feature)
const char *feature;
{
- int i;
- char *buf;
+ VALUE fname, path;
if (rb_feature_p(feature, 0, Qfalse))
return Qtrue;
- if (!loading_tbl) return Qfalse;
- if (st_lookup(loading_tbl, (st_data_t)feature, 0)) return Qtrue;
- buf = ALLOCA_N(char, strlen(feature)+8);
- strcpy(buf, feature);
- for (i=0; ; i++) {
- if (!loadable_ext[i]) break;
- strcpy(buf+strlen(feature), loadable_ext[i]);
- if (st_lookup(loading_tbl, (st_data_t)buf, 0)) return Qtrue;
+ if (search_required(rb_str_new2(feature), &fname, &path) != 0) {
+ feature = RSTRING_PTR(fname);
+ if (rb_feature_p(feature, strrchr(feature, '.'), Qfalse))
+ return Qtrue;
}
return Qfalse;
@@ -7009,17 +7025,39 @@ rb_provide(feature)
}
-static int
-load_wait(ftptr)
- char *ftptr;
+static char *
+load_lock(ftptr)
+ const char *ftptr;
{
st_data_t th;
- if (!loading_tbl) return Qfalse;
- if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse;
+ if (!loading_tbl ||
+ !st_lookup(loading_tbl, (st_data_t)ftptr, &th))
+ {
+ /* loading ruby library should be serialized. */
+ if (!loading_tbl) {
+ loading_tbl = st_init_strtable();
+ }
+ /* partial state */
+ ftptr = ruby_strdup(ftptr);
+ st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
+ return (char *)ftptr;
+ }
do {
- if ((rb_thread_t)th == curr_thread) return Qtrue;
+ if ((rb_thread_t)th == curr_thread) return 0;
CHECK_INTS;
} while (st_lookup(loading_tbl, (st_data_t)ftptr, &th));
- return Qtrue;
+ return 0;
+}
+
+static void
+load_unlock(const char *ftptr)
+{
+ if (ftptr) {
+ st_data_t key = (st_data_t)ftptr;
+
+ if (st_delete(loading_tbl, &key, 0)) {
+ free((char *)key);
+ }
+ }
}
@@ -7063,14 +7101,14 @@ search_required(fname, featurep, path)
*featurep = fname;
*path = 0;
- ext = strrchr(ftptr = RSTRING(fname)->ptr, '.');
+ ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
if (ext && !strchr(ext, '/')) {
if (strcmp(".rb", ext) == 0) {
if (rb_feature_p(ftptr, ext, Qtrue)) return 'r';
- if (*path = rb_find_file(fname)) return 'r';
+ if ((*path = rb_find_file(fname)) != 0) return 'r';
return 0;
}
else if (IS_SOEXT(ext)) {
if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr);
+ tmp = rb_str_new(RSTRING_PTR(fname), ext-RSTRING_PTR(fname));
*featurep = tmp;
#ifdef DLEXT2
@@ -7091,18 +7129,16 @@ search_required(fname, featurep, path)
else if (IS_DLEXT(ext)) {
if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- if (*path = rb_find_file(fname)) return 's';
+ if ((*path = rb_find_file(fname)) != 0) return 's';
}
}
tmp = fname;
- switch (type = rb_find_file_ext(&tmp, loadable_ext)) {
+ type = rb_find_file_ext(&tmp, loadable_ext);
+ *featurep = tmp;
+ switch (type) {
case 0:
- if ((ext = rb_feature_p(ftptr, 0, Qfalse))) {
- type = strcmp(".rb", ext);
- break;
- }
- return 0;
+ ftptr = RSTRING_PTR(tmp);
+ return rb_feature_p(ftptr, 0, Qfalse);
default:
- *featurep = tmp;
ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
if (rb_feature_p(ftptr, ext, !--type)) break;
@@ -7152,16 +7188,9 @@ rb_require_safe(fname, safe)
found = search_required(fname, &feature, &path);
if (found) {
- if (!path || load_wait(RSTRING(feature)->ptr)) {
+ if (!path || !(ftptr = load_lock(RSTRING_PTR(feature)))) {
result = Qfalse;
}
else {
ruby_safe_level = 0;
- /* loading ruby library should be serialized. */
- if (!loading_tbl) {
- loading_tbl = st_init_strtable();
- }
- /* partial state */
- ftptr = ruby_strdup(RSTRING_PTR(feature));
- st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
switch (found) {
case 'r':
@@ -7190,9 +7219,5 @@ rb_require_safe(fname, safe)
SCOPE_SET(saved.vmode);
ruby_safe_level = saved.safe;
- if (ftptr) {
- if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
- free(ftptr);
- }
- }
+ load_unlock(ftptr);
if (state) JUMP_TAG(state);
if (NIL_P(result)) {
@@ -7213,4 +7238,22 @@ rb_require(fname)
}
+void
+ruby_init_ext(name, init)
+ const char *name;
+ void (*init) _((void));
+{
+ ruby_current_node = 0;
+ ruby_sourcefile = rb_source_filename(name);
+ ruby_sourceline = 0;
+ ruby_frame->last_func = 0;
+ ruby_frame->orig_func = 0;
+ SCOPE_SET(SCOPE_PUBLIC);
+ if (load_lock(name)) {
+ (*init)();
+ rb_provide(name);
+ load_unlock(name);
+ }
+}
+
static void
secure_visibility(self)
Index: ext/extmk.rb
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/ext/extmk.rb,v
retrieving revision 1.44.2.37
diff -U 2 -p -r1.44.2.37 extmk.rb
--- ext/extmk.rb 19 Oct 2006 16:03:45 -0000 1.44.2.37
+++ ext/extmk.rb 19 Dec 2006 15:54:28 -0000
@@ -452,12 +452,9 @@ unless $extlist.empty?
#include "ruby.h"
-#define init(func, name) { \
- void func _((void)); \
- ruby_sourcefile = src = rb_source_filename(name); \
- func(); \
- rb_provide(src); \
-}
+#define init(func, name) {void func _((void)); ruby_init_ext(name, func);}
+
+void ruby_init_ext _((const char *name, void (*init)(void)));
-void Init_ext _((void))\n{\n char *src;#$extinit}
+void Init_ext _((void))\n{\n#$extinit}
}
if !modified?(extinit.c, MTIMES) || IO.read(extinit.c) != src
--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
中田 伸悦