summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h6
-rw-r--r--mrbgems/mruby-hash-ext/mrblib/hash.rb4
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb2
-rw-r--r--src/gc.c48
-rw-r--r--src/kernel.c2
-rw-r--r--src/string.c4
6 files changed, 60 insertions, 6 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 4af607b26..a20693394 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -613,7 +613,13 @@ MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg);
MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv);
MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c);
+/* mrb_gc_protect() leaves the object in the arena */
MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj);
+/* mrb_gc_register() keeps the object from GC. */
+MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj);
+/* mrb_gc_unregister() removes the object from GC root. */
+MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj);
+
MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val))
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb
index 5056d0720..ec8bd05fb 100644
--- a/mrbgems/mruby-hash-ext/mrblib/hash.rb
+++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -130,7 +130,7 @@ class Hash
elsif none != NONE
none
else
- raise RuntimeError, "Key not found: #{key}"
+ raise KeyError, "Key not found: #{key}"
end
else
self[key]
@@ -156,7 +156,7 @@ class Hash
self.each do |k, v|
self.delete(k) if block.call(k, v)
- end
+ end
self
end
diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb
index 4950ef354..ef25acbe7 100644
--- a/mrbgems/mruby-hash-ext/test/hash.rb
+++ b/mrbgems/mruby-hash-ext/test/hash.rb
@@ -79,7 +79,7 @@ assert('Hash#fetch') do
begin
h.fetch("gnu")
rescue => e
- assert_kind_of(StandardError, e);
+ assert_kind_of(KeyError, e);
end
end
diff --git a/src/gc.c b/src/gc.c
index 15e1bd423..885368f37 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -385,6 +385,7 @@ gc_protect(mrb_state *mrb, struct RBasic *p)
mrb->arena[mrb->arena_idx++] = p;
}
+/* mrb_gc_protect() leaves the object in the arena */
MRB_API void
mrb_gc_protect(mrb_state *mrb, mrb_value obj)
{
@@ -392,6 +393,53 @@ mrb_gc_protect(mrb_state *mrb, mrb_value obj)
gc_protect(mrb, mrb_basic_ptr(obj));
}
+#define GC_ROOT_NAME "_gc_root_"
+
+/* mrb_gc_register() keeps the object from GC.
+
+ Register your object when it's exported to C world,
+ without reference from Ruby world, e.g. callback
+ arguments. Don't forget to remove the obejct using
+ mrb_gc_unregister, otherwise your object will leak.
+*/
+
+MRB_API void
+mrb_gc_register(mrb_state *mrb, mrb_value obj)
+{
+ mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ mrb_value table = mrb_gv_get(mrb, root);
+
+ if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) {
+ table = mrb_ary_new(mrb);
+ mrb_gv_set(mrb, root, table);
+ }
+ mrb_ary_push(mrb, table, obj);
+}
+
+/* mrb_gc_unregister() removes the object from GC root. */
+MRB_API void
+mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
+{
+ mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ mrb_value table = mrb_gv_get(mrb, root);
+ struct RArray *a;
+ mrb_int i, j;
+
+ if (mrb_nil_p(table)) return;
+ if (mrb_type(table) != MRB_TT_ARRAY) {
+ mrb_gv_set(mrb, root, mrb_nil_value());
+ return;
+ }
+ a = mrb_ary_ptr(table);
+ mrb_ary_modify(mrb, a);
+ for (i=j=0; i<a->len; i++) {
+ if (!mrb_obj_eq(mrb, a->ptr[i], obj)) {
+ a->ptr[j++] = a->ptr[i];
+ }
+ }
+ a->len = j;
+}
+
MRB_API struct RBasic*
mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
{
diff --git a/src/kernel.c b/src/kernel.c
index 225f7fa54..09d869f9d 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -660,7 +660,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) {
MRB_CLASS_ORIGIN(klass);
- prepended = 1;
+ prepended = TRUE;
}
oldklass = 0;
diff --git a/src/string.c b/src/string.c
index e93fd4606..12aefa8a0 100644
--- a/src/string.c
+++ b/src/string.c
@@ -56,7 +56,7 @@ mrb_utf8_from_locale(const char *str, size_t len)
if (len == 0)
return strdup("");
if (len == -1)
- len = strlen(str);
+ len = strlen(str);
wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0);
wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
if (!wcsp)
@@ -86,7 +86,7 @@ mrb_locale_from_utf8(const char *utf8, size_t len)
if (len == 0)
return strdup("");
if (len == -1)
- len = strlen(utf8);
+ len = strlen(utf8);
wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
if (!wcsp)