[macruby-changes] [217] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sun May 25 01:25:09 PDT 2008
Revision: 217
http://trac.macosforge.org/projects/ruby/changeset/217
Author: lsansonetti at apple.com
Date: 2008-05-25 01:25:09 -0700 (Sun, 25 May 2008)
Log Message:
-----------
implemented ObjectSpace finalizers, make sure irb reads /etc/irbrc (#59)
Modified Paths:
--------------
MacRuby/trunk/gc.c
MacRuby/trunk/include/ruby/intern.h
MacRuby/trunk/lib/irb/init.rb
MacRuby/trunk/objc.m
MacRuby/trunk/variable.c
Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c 2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/gc.c 2008-05-25 08:25:09 UTC (rev 217)
@@ -2397,11 +2397,23 @@
*
*/
+#if WITH_OBJC
+static CFMutableDictionaryRef __os_finalizers = NULL;
+#endif
+
static VALUE
undefine_final(VALUE os, VALUE obj)
{
#if WITH_OBJC
- rb_notimplement();
+ if (__os_finalizers != NULL)
+ CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
+
+ if (rb_objc_is_non_native(obj)) {
+ rb_objc_flag_set(obj, FL_FINALIZE, false);
+ }
+ else {
+ FL_UNSET(obj, FL_FINALIZE);
+ }
#else
rb_objspace_t *objspace = &rb_objspace;
if (finalizer_table) {
@@ -2424,7 +2436,38 @@
define_final(int argc, VALUE *argv, VALUE os)
{
#if WITH_OBJC
- rb_notimplement();
+ VALUE obj, block, table;
+
+ if (__os_finalizers == NULL)
+ __os_finalizers = CFDictionaryCreateMutable(NULL, 0, NULL,
+ &kCFTypeDictionaryValueCallBacks);
+
+ rb_scan_args(argc, argv, "11", &obj, &block);
+ if (argc == 1) {
+ block = rb_block_proc();
+ }
+ else if (!rb_respond_to(block, rb_intern("call"))) {
+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
+ rb_obj_classname(block));
+ }
+
+ table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
+ (const void *)obj);
+
+ if (table == 0) {
+ table = rb_ary_new();
+ CFDictionarySetValue(__os_finalizers, (const void *)obj,
+ (const void *)table);
+ }
+
+ rb_ary_push(table, block);
+
+ if (rb_objc_is_non_native(obj)) {
+ rb_objc_flag_set(obj, FL_FINALIZE, true);
+ }
+ else {
+ FL_SET(obj, FL_FINALIZE);
+ }
#else
rb_objspace_t *objspace = &rb_objspace;
VALUE obj, block, table;
@@ -2459,7 +2502,30 @@
rb_gc_copy_finalizer(VALUE dest, VALUE obj)
{
#if WITH_OBJC
- /* TODO */
+ VALUE table;
+
+ if (__os_finalizers == NULL)
+ return;
+
+ if (rb_objc_is_non_native(obj)) {
+ if (!rb_objc_flag_check(obj, FL_FINALIZE))
+ return;
+ }
+ else {
+ if (!FL_TEST(obj, FL_FINALIZE))
+ return;
+ }
+
+ table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
+ (const void *)obj);
+
+ if (table == 0) {
+ CFDictionaryRemoveValue(__os_finalizers, (const void *)dest);
+ }
+ else {
+ CFDictionarySetValue(__os_finalizers, (const void *)dest,
+ (const void *)table);
+ }
#else
rb_objspace_t *objspace = &rb_objspace;
VALUE table;
@@ -2533,6 +2599,14 @@
CFArrayAppendValue(__exit_finalize, (void *)v);
}
+static void rb_call_os_finalizer2(VALUE, VALUE);
+
+static void
+os_finalize_cb(const void *key, const void *val, void *context)
+{
+ rb_call_os_finalizer2((VALUE)key, (VALUE)val);
+}
+
void
rb_gc_call_finalizer_at_exit(void)
{
@@ -2545,9 +2619,17 @@
v = (VALUE)CFArrayGetValueAtIndex((CFArrayRef)__exit_finalize, i);
rb_objc_finalize_pure_ruby_obj(v);
}
+ CFArrayRemoveAllValues(__exit_finalize);
+ CFRelease(__exit_finalize);
}
- CFArrayRemoveAllValues(__exit_finalize);
- CFRelease(__exit_finalize);
+
+ if (__os_finalizers != NULL) {
+ CFDictionaryApplyFunction((CFDictionaryRef)__os_finalizers,
+ os_finalize_cb, NULL);
+ CFDictionaryRemoveAllValues(__os_finalizers);
+ CFRelease(__os_finalizers);
+ }
+
auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL);
}
@@ -2917,20 +2999,71 @@
static void (*old_batch_invalidate)(auto_zone_t *,
auto_zone_foreach_object_t, auto_zone_cursor_t, size_t);
+static VALUE
+run_single_final(VALUE arg)
+{
+ VALUE *args = (VALUE *)arg;
+ rb_eval_cmd(args[0], args[1], (int)args[2]);
+ return Qnil;
+}
+
static void
+rb_call_os_finalizer2(VALUE obj, VALUE table)
+{
+ long i, count;
+ VALUE args[3];
+ int status, critical_save;
+
+ critical_save = rb_thread_critical;
+ rb_thread_critical = Qtrue;
+
+ args[1] = rb_ary_new3(1, rb_obj_id(obj));
+ args[2] = (VALUE)rb_safe_level();
+
+ for (i = 0, count = RARRAY_LEN(table); i < count; i++) {
+ args[0] = RARRAY_AT(table, i);
+ rb_protect(run_single_final, (VALUE)args, &status);
+ }
+
+ rb_thread_critical = critical_save;
+}
+
+static void
+rb_call_os_finalizer(void *obj)
+{
+ if (__os_finalizers != NULL) {
+ VALUE table;
+
+ table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
+ (const void *)obj);
+
+ if (table != 0) {
+ rb_call_os_finalizer2((VALUE)obj, table);
+ CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
+ }
+ }
+}
+
+static void
__rb_objc_finalize(void *obj, void *data)
{
if (rb_objc_is_non_native((VALUE)obj)) {
static SEL sel = NULL;
- rb_objc_remove_keys(obj);
- rb_free_generic_ivar((VALUE)obj, true);
+ long flag;
+ flag = rb_objc_remove_flags(obj);
+ if ((flag & FL_FINALIZE) == FL_FINALIZE)
+ rb_call_os_finalizer(obj);
+ if ((flag & FL_EXIVAR) == FL_EXIVAR)
+ rb_free_generic_ivar((VALUE)obj);
if (sel == NULL)
sel = sel_registerName("finalize");
objc_msgSend(obj, sel);
}
else {
+ if (FL_TEST(obj, FL_FINALIZE))
+ rb_call_os_finalizer(obj);
if (FL_TEST(obj, FL_EXIVAR))
- rb_free_generic_ivar((VALUE)obj, false);
+ rb_free_generic_ivar((VALUE)obj);
}
}
Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h 2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/include/ruby/intern.h 2008-05-25 08:25:09 UTC (rev 217)
@@ -656,7 +656,7 @@
void rb_copy_generic_ivar(VALUE,VALUE);
void rb_mark_generic_ivar(VALUE);
void rb_mark_generic_ivar_tbl(void);
-void rb_free_generic_ivar(VALUE,bool);
+void rb_free_generic_ivar(VALUE);
VALUE rb_ivar_get(VALUE, ID);
VALUE rb_ivar_set(VALUE, ID, VALUE);
VALUE rb_ivar_defined(VALUE, ID);
Modified: MacRuby/trunk/lib/irb/init.rb
===================================================================
--- MacRuby/trunk/lib/irb/init.rb 2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/lib/irb/init.rb 2008-05-25 08:25:09 UTC (rev 217)
@@ -240,6 +240,7 @@
yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"}
yield proc{|rc| home+"/_irb#{rc}"}
yield proc{|rc| home+"/$irb#{rc}"}
+ yield proc{|rc| "/etc/irb#{rc}"}
end
# loading modules
Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m 2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/objc.m 2008-05-25 08:25:09 UTC (rev 217)
@@ -2661,10 +2661,16 @@
CFDictionarySetValue(__obj_flags, obj, (void *)v);
}
-void
-rb_objc_remove_keys(const void *obj)
+long
+rb_objc_remove_flags(const void *obj)
{
- CFDictionaryRemoveValue(__obj_flags, obj);
+ long flag;
+ if (CFDictionaryGetValueIfPresent(__obj_flags, obj,
+ (const void **)&flag)) {
+ CFDictionaryRemoveValue(__obj_flags, obj);
+ return flag;
+ }
+ return 0;
}
static void
@@ -2914,3 +2920,13 @@
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopDefaultMode);
}
}
+
+ at interface Protocol
+ at end
+
+ at implementation Protocol (MRFindProtocol)
++(id)protocolWithName:(NSString *)name
+{
+ return (id)objc_getProtocol([name UTF8String]);
+}
+ at end
Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c 2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/variable.c 2008-05-25 08:25:09 UTC (rev 217)
@@ -844,7 +844,7 @@
}
static void
-generic_ivar_set(VALUE obj, ID id, VALUE val, int pure)
+generic_ivar_set(VALUE obj, ID id, VALUE val)
{
#if WITH_OBJC
CFMutableDictionaryRef obj_dict;
@@ -879,8 +879,6 @@
(const void *)obj_dict);
CFMakeCollectable(obj_dict);
}
- if (!pure)
- FL_SET(obj, FL_EXIVAR);
CFDictionarySetValue(obj_dict, (const void *)id, (const void *)val);
#else
st_table *tbl;
@@ -1012,21 +1010,11 @@
#endif
void
-rb_free_generic_ivar(VALUE obj, bool lookup)
+rb_free_generic_ivar(VALUE obj)
{
#if WITH_OBJC
- if (generic_iv_dict != NULL) {
- if (lookup) {
- if (CFDictionaryGetValueIfPresent(generic_iv_dict,
- (const void *)obj, NULL)) {
- CFDictionaryReplaceValue(generic_iv_dict, (const void *)obj,
- NULL);
- }
- }
- else {
- CFDictionaryRemoveValue(generic_iv_dict, (const void *)obj);
- }
- }
+ if (generic_iv_dict != NULL)
+ CFDictionaryRemoveValue(generic_iv_dict, (const void *)obj);
#else
st_data_t tbl;
@@ -1157,7 +1145,8 @@
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
#if WITH_OBJC
if (rb_objc_is_non_native(obj)) {
- generic_ivar_set(obj, id, val, 1);
+ rb_objc_flag_set(obj, FL_EXIVAR, true);
+ generic_ivar_set(obj, id, val);
return val;
}
#endif
@@ -1221,7 +1210,8 @@
st_insert(RCLASS_IV_TBL(obj), id, val);
break;
default:
- generic_ivar_set(obj, id, val, 0);
+ generic_ivar_set(obj, id, val);
+ FL_SET(obj, FL_EXIVAR);
break;
}
return val;
@@ -1316,9 +1306,11 @@
if (generic_iv_dict != NULL) {
CFDictionaryRef obj_dict;
- obj_dict = (CFDictionaryRef)CFDictionaryGetValue((CFDictionaryRef)generic_iv_dict, (const void *)obj);
+ obj_dict = (CFDictionaryRef)CFDictionaryGetValue(
+ (CFDictionaryRef)generic_iv_dict, (const void *)obj);
if (obj_dict != NULL)
- CFDictionaryApplyFunction(obj_dict, (CFDictionaryApplierFunction)func, (void *)arg);
+ CFDictionaryApplyFunction(obj_dict,
+ (CFDictionaryApplierFunction)func, (void *)arg);
}
#else
if (!generic_iv_tbl) break;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080525/6264dcf2/attachment.htm
More information about the macruby-changes
mailing list